Android網(wǎng)絡(luò)與數(shù)據(jù)存儲(chǔ)——網(wǎng)絡(luò)編程數(shù)據(jù)處理(網(wǎng)絡(luò)請(qǐng)求熄驼,解析xml,解析Json)

手機(jī)的優(yōu)勢(shì)是攜帶方便烘豹,可以隨時(shí)打開瓜贾,而且手機(jī)通常總是處于聯(lián)網(wǎng)狀態(tài)的携悯,所以網(wǎng)絡(luò)支持對(duì)于手機(jī)很重要祭芦。而且Java的網(wǎng)絡(luò)編程完全適用于Android網(wǎng)絡(luò)編程。

一.網(wǎng)絡(luò)請(qǐng)求


1.URL

在真正學(xué)習(xí)網(wǎng)絡(luò)請(qǐng)求之前有必要了解一下什么是URL憔鬼,URL的英文全拼是Uniform Resource Locator龟劲,翻譯過來為統(tǒng)一資源定位器,大概意思就是URL是指向互聯(lián)網(wǎng)資源的指針轴或。

這里說的資源可以是文件或目錄昌跌,也可以是對(duì)象的引用,例如對(duì)數(shù)據(jù)庫(kù)或搜索引擎的查詢照雁。

URL的組成:協(xié)議名蚕愤、主機(jī)、端口和資源饺蚊。即滿足如下格式:

protocol://host:port/resourceName

例如 google的URL地址:

https://www.google.com

URL類提供了多個(gè)構(gòu)造器用于創(chuàng)建URL對(duì)象萍诱,一旦獲得了URL對(duì)象之后,就可以訪問該URL對(duì)象對(duì)應(yīng)的資源了污呼。

2.Http網(wǎng)絡(luò)請(qǐng)求

Android中的Http網(wǎng)絡(luò)請(qǐng)求有兩種方式:

  • HttpURLConnection
  • HttpClient(已不推薦使用)

既然HttpClient已被棄用裕坊,那就用HttpURLConnection。

HttpURLConnection繼承了URLConnection曙求,可用于向指定網(wǎng)站發(fā)送GET請(qǐng)求碍庵、POST請(qǐng)求。提供了一下方法:

  • HttpURLConnection openConnection():返回一個(gè)HttpURLConnection對(duì)象悟狱,表示到URL所引用的遠(yuǎn)程對(duì)象的連接静浴。
  • int getResponseCode():獲取服務(wù)器的響應(yīng)代碼。例如:200表示服務(wù)器成功響應(yīng)挤渐,404表示沒響應(yīng)苹享。
  • String getResponseMessage():獲取服務(wù)器的響應(yīng)消息。
  • String getRequestMethod():獲取發(fā)送請(qǐng)求的方法。
  • void setRequestMethod():設(shè)置發(fā)送請(qǐng)求的方法得问。
  • void setConnectTimeout():設(shè)置連接超時(shí)時(shí)間囤攀。
  • void setReadTimeout():設(shè)置讀取超時(shí)時(shí)間。

下邊寫一個(gè)請(qǐng)求百度API獲取全國(guó)城市的方法來使用上面提到的方法宫纬。代碼如下:

public void requestCityData(final String urlString) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(urlString);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    connection.connect();
                    if (connection.getResponseCode() == 200) {
                        InputStream inputStream = connection.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        String line;
                        StringBuilder builder = new StringBuilder();
                        while ((line = reader.readLine()) != null) {
                            builder.append(line);
                        }
                        reader.close();
                        String result = builder.toString();
                        Message msg = new Message();
                        msg.what = 0;
                        msg.obj = result;
                        handler.sendMessage(msg);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
}

從以上代碼可以看出請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的方法可以分為以下步驟:

  • 創(chuàng)建URL對(duì)象url焚挠。
  • 通過url.openConnection()獲取HttpURLConnection對(duì)象connection。
  • 設(shè)置請(qǐng)求方式漓骚、連接延遲蝌衔、讀取延遲、連接蝌蹂。
  • 通過connection.getResponseCode()獲取響應(yīng)碼來判斷是否連接成功噩斟。
  • 如果連接成功,接下來的讀取文件和Java的讀文件操作一樣孤个。
  • 由于請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的操作屬于耗時(shí)操作剃允,所以應(yīng)該把整個(gè)請(qǐng)求操作放在了子線程(處理異步數(shù)據(jù)有兩種方式:handler和AsyncTask,這里用handler進(jìn)行實(shí)現(xiàn)齐鲤,下一篇中的利用多線程下載會(huì)用AsyncTask)斥废,最后把請(qǐng)求到的數(shù)據(jù)通過handler.sendMessage()方法發(fā)送到主線程,在handler中的handleMessage()方法中對(duì)請(qǐng)求到的數(shù)據(jù)進(jìn)行處理给郊。handler代碼如下:
Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0:
                    String cityData = msg.obj.toString();
                    Log.d("CityActivity", cityData);
                    break;
            }
        }
};

這里的handler只是簡(jiǎn)單的打印了一下請(qǐng)求到的數(shù)據(jù)营袜。

到目前為止,還不算請(qǐng)求完成丑罪,因?yàn)檫@里用到了網(wǎng)絡(luò)荚板,要想獲取網(wǎng)絡(luò)上的數(shù)據(jù),該應(yīng)用必須有請(qǐng)求網(wǎng)絡(luò)的權(quán)限吩屹,在AndroidManifest.xml中加入網(wǎng)絡(luò)權(quán)限即可跪另。

<uses-permission android:name="android.permission.INTERNET" />

二.解析xml


如果請(qǐng)求到的數(shù)據(jù)為xml類型的,就需要把xml類型的數(shù)據(jù)解析成我們想要的類型或從xml類型的數(shù)據(jù)中解析出我們想要的數(shù)據(jù)煤搜。

解析xml類型數(shù)據(jù)有兩種方式:

  • SAX:基于事件驅(qū)動(dòng)的解析(解析器+事件處理器)免绿,較復(fù)雜。
  • PULL
  • DOM:基于文件流擦盾。

SAX嘲驾、PULL是一個(gè)標(biāo)簽一個(gè)標(biāo)簽讀,分段加載迹卢;DOM是整個(gè)文件讀取出來辽故,然后加載。

1.SAX

利用SAX解析如下xml中的id腐碱、url以及item text誊垢。

<?xml version="1.0" encoding="utf-8"?>
<web>
    <item id = "0" url = "http://www.baidu.com" >百度</item>
    <item id = "1" url = "http://www.sogou.com" >搜狗</item>
    <item id = "2" url = "http://www.sohu.com" >搜狐</item>
</web>

先新建一個(gè)SAXParseHandler類繼承自DefaultHandler,并實(shí)現(xiàn)startDocument()、startElement()喂走、characters()殃饿、endElement()、endDocument()這五個(gè)方法芋肠。

public class SAXParseHandler extends DefaultHandler {

    private List<WebURL> mWebURLs;
    private WebURL mWebURL;
    private boolean state = false;

    @Override
    public void startDocument() throws SAXException {
        mWebURLs = new ArrayList<>();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        mWebURL = new WebURL();
        if (TextUtils.equals(localName, "item")){
            for (int i = 0; i < attributes.getLength(); i++) {
                if (TextUtils.equals(attributes.getLocalName(i), "id")){
                    mWebURL.setmID(Integer.parseInt(attributes.getValue(i)));
                }else if (TextUtils.equals(attributes.getLocalName(i), "url")){
                    mWebURL.setmUrl(attributes.getValue(i));
                }
            }
            state = true;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String content = String.valueOf(ch, start, length);
        if (state) {
            mWebURL.setmContent(content);
            state = false;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (TextUtils.equals(localName, "item")){
            mWebURLs.add(mWebURL);
        }
    }

    @Override
    public void endDocument() throws SAXException {
    }
}

以上代碼中startDocument()表示解析到最外層的標(biāo)簽乎芳,進(jìn)行一些初始化操作,startElement()表示解析到子標(biāo)簽帖池,通過attributes來獲取該標(biāo)簽的屬性id和url秒咐,characters()表示子標(biāo)簽開始標(biāo)簽和結(jié)束標(biāo)簽中間的內(nèi)容,在這里通過轉(zhuǎn)換ch可以獲取到碘裕,endElement()表示結(jié)束子標(biāo)簽,在這個(gè)方法中將獲取到的信息進(jìn)行保存攒钳,endDocument()表示解析結(jié)束帮孔。

SAXParseHandler類將xml的每一個(gè)標(biāo)簽進(jìn)行了遍歷,接下來就是通過SAX解析器進(jìn)行解析了不撑。解析代碼如下:

private void testSAXParse() throws ParserConfigurationException, SAXException, IOException {
        //定義一個(gè)factory API文兢,能夠配置和獲取一個(gè)SAX解析器去解析xml
        //SAXParserFactory.newInstance();返回Android的接口SAXParserFactory,不像其他Java接口焕檬,該方法不能產(chǎn)生系統(tǒng)屬性
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();//屬性文件或服務(wù)API
        //定義一個(gè)API包裹XMLReader實(shí)現(xiàn)類
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //讀一個(gè)xml文檔的接口姆坚,用于回調(diào)
        XMLReader xmlReader = saxParser.getXMLReader();
        saxParseHandler = new SAXParseHandler();
        //將saxParseHandler的實(shí)例設(shè)置到XMLReader中
        xmlReader.setContentHandler(saxParseHandler);
        InputStream inputStream = getResources().openRawResource(R.raw.test);
        InputSource inputSource = new InputSource(inputStream);
        //開始執(zhí)行解析
        xmlReader.parse(inputSource);
    }

以上代碼中的注釋寫的很詳細(xì),就不在啰嗦了实愚。

2.PULL

待補(bǔ)充...

三.解析Json


Android中解析Json的類有JSONObject和JSONArray兼呵。

格式化Json數(shù)據(jù)的網(wǎng)址:jsonlint.com

開源庫(kù):對(duì)開源庫(kù)還未進(jìn)行研究,待研究了回來補(bǔ)充...

  • GSON
  • fastJson

通過JSONObject和JSONArray來對(duì)下面一段Json數(shù)據(jù)進(jìn)行解析腊敲。

{city_info: [ 
{city: "南子島", cnty: "中國(guó)", id: "CN101310230", lat: "11.26", lon: "114.20", prov: "海南" }, 
{city: "北京", cnty: "中國(guó)", id: "CN101010100", lat: "39.904000", lon: "116.391000", prov: "直轄市" }, ... 
] }

寫一個(gè)方法對(duì)以上Json數(shù)據(jù)進(jìn)行解析击喂,代碼如下:

public List<CityInfo> parseCityData(String cityData) {
        List<CityInfo> cityInfos = new ArrayList<>();
        try {
            JSONObject jsonObject = new JSONObject(cityData);
            JSONArray jsonArray = jsonObject.getJSONArray("city_info");

            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject cityObject = (JSONObject) jsonArray.get(i);
                String city = cityObject.getString("city");
                String prov = cityObject.getString("prov");
                CityInfo cityInfo = new CityInfo(city, prov);
                cityInfos.add(cityInfo);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return cityInfos;
}

通過new JSONObject()獲取整個(gè)JSONObject對(duì)象,然后利用getJSONArray()獲取city_info對(duì)應(yīng)的Json數(shù)組碰辅,然后再通過Json數(shù)組的get方法獲取數(shù)組中的每一個(gè)JSONObject對(duì)象懂昂,通過關(guān)鍵字獲取我們想要的數(shù)據(jù),最后將數(shù)據(jù)存入列表没宾。整個(gè)Json數(shù)據(jù)解析完畢凌彬。

四.網(wǎng)絡(luò)狀態(tài)處理


網(wǎng)絡(luò)狀態(tài)處理:可以判斷是否連接網(wǎng)絡(luò),還可以區(qū)分移動(dòng)網(wǎng)絡(luò)流量還是WiFi網(wǎng)絡(luò)流量

  • ConnectivityManager
  • NetworkInfo

五.擴(kuò)展


  1. 下載電影循衰、音樂的本質(zhì)铲敛?
    網(wǎng)絡(luò)請(qǐng)求
  2. 斷點(diǎn)下載
    記錄http的Head,下載時(shí)間会钝,下載了哪些東西原探。
  3. 常用網(wǎng)絡(luò)開源庫(kù)
  • android-async-http
  • volley
  • OKHttp
  • Retrofit
  1. 封裝請(qǐng)求及通用設(shè)置
  • 封裝能用Header
  • 請(qǐng)求參數(shù)封裝
  1. 封裝結(jié)果處理
  • 能用錯(cuò)誤碼處理
  • 數(shù)據(jù)轉(zhuǎn)換校驗(yàn)
  1. 攔截請(qǐng)求設(shè)置及代理
  • Fiddler(Windows)
  • Charles(Mac)
  • wifi設(shè)置代理
  1. 技巧
  • Postman查詢API
  • Restful API
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咽弦,更是在濱河造成了極大的恐慌徒蟆,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件型型,死亡現(xiàn)場(chǎng)離奇詭異段审,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)闹蒜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門寺枉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绷落,你說我怎么就攤上這事姥闪。” “怎么了砌烁?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵筐喳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我函喉,道長(zhǎng)避归,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任管呵,我火速辦了婚禮梳毙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捐下。我一直安慰自己账锹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布坷襟。 她就那樣靜靜地躺著牌废,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啤握。 梳的紋絲不亂的頭發(fā)上鸟缕,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音排抬,去河邊找鬼懂从。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蹲蒲,可吹牛的內(nèi)容都是我干的番甩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼届搁,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼缘薛!你這毒婦竟也來了窍育?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宴胧,失蹤者是張志新(化名)和其女友劉穎漱抓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恕齐,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乞娄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了显歧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仪或。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖士骤,靈堂內(nèi)的尸體忽然破棺而出范删,到底是詐尸還是另有隱情,我是刑警寧澤拷肌,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布到旦,位于F島的核電站,受9級(jí)特大地震影響廓块,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜契沫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一带猴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懈万,春花似錦拴清、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至涕侈,卻和暖如春沪停,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裳涛。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工木张, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人端三。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓舷礼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親郊闯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妻献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蛛株,服務(wù)發(fā)現(xiàn),斷路器育拨,智...
    卡卡羅2017閱讀 134,694評(píng)論 18 139
  • 1 XML解析No29 【 XML:可拓展標(biāo)記語(yǔ)言谨履,語(yǔ)言和HTML類似,也是一種標(biāo)記語(yǔ)言至朗。 特點(diǎn):標(biāo)記是自定義...
    征程_Journey閱讀 1,656評(píng)論 0 9
  • JSON JSON和XML都是需要解析的 JSON是一種輕量級(jí)的數(shù)據(jù)格式屉符,一般用于數(shù)據(jù)交互服務(wù)器返回給客戶端的數(shù)據(jù)...
    JonesCxy閱讀 1,860評(píng)論 2 10
  • 從小是個(gè)無(wú)肉不歡的我特別喜歡的就是過年,因?yàn)槊糠赀^年的時(shí)候家里就會(huì)燒一桌子好吃的锹引,當(dāng)然必少不了我最愛吃的紅燒肉矗钟。 ...
    3f17274cd933閱讀 383評(píng)論 0 0
  • 多希望有一天突然驚醒吨艇,發(fā)現(xiàn)自己在高中的一節(jié)課上睡著了,現(xiàn)在經(jīng)歷的一切都是一場(chǎng)夢(mèng)腾啥,桌上滿是你的口水东涡。你告訴同桌...
    風(fēng)雪依然閱讀 318評(píng)論 0 1