一起來開發Android的天氣軟體(三),android天氣
距離上一篇一起來開發Android天氣軟體二的時間又將近半個月了,之間一直因為有事而沒有更新實在抱歉,最近會加快更新的步伐,爭取在2015年到來前寫完這系列的博文,上一章我們已經使用LitePal架構搭建好了我們所需的資料庫,這一章的內容將主要完成關於從中國天氣網擷取資料的網路通訊操作,之前有學習過Android開發的同學應該都知道,Android實現互連網通訊主要有兩種方法,一種使用HTTPURLCONNECTION,一種使用HttpClient的方式,而我們今天將使用不同於以上兩種的方式,使用Volley架構完成我們的網路通訊服務。
Volley架構呢是 2013年在Google I/O大會上推出了一個新的網路通訊架構。Volley非常的簡單易用,在通訊效能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行資料量不大,但通訊頻繁的網路操作,也比較適合我們這款軟體吧。
一、如何擷取資料 如何擷取全國所有省份的資訊呢,我們只要要訪問以下網址 http://www.weather.com.cn/data/list3/city.xml,就會返回中國所有省份的名稱和代號,如下所示。01|北京,02|上海,03|天津,21|浙江等等,我們可以看到城市與其代號之間通過|號相隔開,省份與省份之間用,號隔開,記住這個結構。之後的之後會用到Regex去截取。 如何查看浙江省下的城市的資訊呢,其實也非常簡單,只需要訪問以下網址http://www.weather.com.cn/data/list3/city21.xml,也就是只需要將省級代號添加至city後面就可以了,伺服器就會返回資料2101|杭州,2102|寧波,2103|溫州等等。 同樣的方法,我們如果想訪問杭州以下的縣市的資訊,只需要city添加2101即可,如下示 http://www.weather.com.cn/data/list3/city2101.xml。 以上我們就可以知道如何獲得全國省市區的資訊了,那麼如何得到某具體城市的天氣呢?以杭州市區為例他的縣級代號為210101,那麼訪問以下網址http://www.weather.com.cn/data/list3/city210101.xml就會返回一個很簡單的資料210101|101210101,後面的就是杭州市區所對應的天氣代號,之後我們在用我們這個得到的代號就可以訪問以下網址http://www.weather.com.cn/data/cityinfo/101210101.html,注意這個網址尾碼是html,不是xml了,寫代碼的時候不要寫錯了,這樣伺服器就會把杭州市區的天氣資訊已json格式的資料返回給我們,如下所示。 {"weatherinfo":{"city":"杭州","cityid":"101210101","temp1":"1℃","temp2":"10℃","weather":"多雲轉晴","img1":"n1.gif","img2":"d0.gif","ptime":"18:00"}}
二、如何?網路通訊 我們現在已經知道訪問的網址的具體地址了,那麼如何通過我們的軟體實現真正的網路通訊呢,接下來我將先以使用HTTPURLCONNCTION方法實現網路的資料擷取,具體的代碼如下所示。
package com.melhc.util;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;public class HttpUtil {/* * 從伺服器端擷取省縣市的資料 */public static void sendHttpRequest(final String address,final HttpCallbackListener listener) {new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubHttpURLConnection connection = null;try {//建立一個url對象URL url = new URL(address);//通過url對象擷取HTTPURLCONNCETION執行個體connection = (HttpURLConnection) url.openConnection();//設定http的請求所使用的方法為get方法connection.setRequestMethod("GET");//自由定製一些屬性,比如設定連線逾時,讀取逾時的毫秒數connection.setConnectTimeout(8000);connection.setReadTimeout(8000);//獲得伺服器返回的輸入資料流InputStream in = connection.getInputStream();//將得到的輸入資料流裝換成String字串BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"));StringBuffer response = new StringBuffer();String line;while ((line = reader.readLine()) != null) {response.append(line);}LogUtil.i("HTTPUtil","------------------>" + response.toString());if (listener != null) {listener.onFinish(response.toString());}} catch (Exception e) {// TODO: handle exceptionif (listener != null) {listener.onError(e);}} finally {if (connection != null) {connection.disconnect();}}}}).start();}}
上面的代碼應該還是比較簡單易懂的,因為網路通訊操作是一個耗時操作,所以不能在主線程中使用,所以我們新開了一個子線程來擷取資料!細心的朋友會發現上面的傳入參數除了目標的訪問網址,還傳入了一個HttpCallBackListener對象,這個是幹嘛用的呢?這裡是用了一個回調機制,因為子線程是不允許有return對象的,而我們返回的資料可能又要運用到另一個類中的方法中使用,那麼如何將該資料在兩個類中傳遞呢,那麼就會運用到回調機制。 先創立一個HttpCallBackListener介面
package com.melhc.util;/* * 網路串連的回掉介面 */public interface HttpCallbackListener {void onFinish(String response);void onError(Exception e);}
然後接該方法作為參數傳入我們的網路通訊類中,其實他的實現方法跟我們Android常用的onCLickListener的實現原來一樣,然後這個介面的具體實現在使用該類的地方實化,從而擷取網路通訊中得到的資料,該介面其實就成為了串連兩個類中的橋樑。
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {@Overridepublic void onFinish(String response) {// TODO Auto-generated method stubboolean result = false;if ("province".equals(type)) {result = Utility.handleProvicesResponse(weatherDB, response);} else if ("city".equals(type)) {result = Utility.handleCitiesResponse(weatherDB, response,selectedProvince);} else if ("county".equals(type)) {result = Utility.handleCountiesResponse(weatherDB,response, selectedCity);}
這個就是具體實作類別中的使用,這個類之後我們後面的博文中具體介紹,在此我們只要注意在主線程中我們才執行個體化了這個HttpCallBackListener介面,通過response參數的傳遞繼續完成接下來的方法。 傳統的網路通訊方法到此呢就講完了,是不是覺得還是挺麻煩的,還得使用什麼回調機制,在Volley中可都不需要了,人家都幫我們封裝好了。三、Volley實現網路通訊 接下來我們就開始正式使用Volley完成上面一摸一樣的通訊流程,只需要三步即可完成網路的發送與響應!首先還是得先下載一下Volley的jar檔案,並且匯入自己的程式中!volley.jar:http://download.csdn.net/detail/u013900875/8279223。接下來按以下三步走即可!
1. 建立一個RequestQueue對象。
2. 建立一個StringRequest對象。
3. 將StringRequest對象添加到RequestQueue裡面。
具體的代碼實現如下所示
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());StringRequest stringRequest = new StringRequest(address,new Response.Listener<String>() {@Overridepublic void onResponse(String response) {LogUtil.i("TAG", "---------------->"+response);boolean result = false;if ("province".equals(type)) {result = Utility.handleProvicesResponse(weatherDB,response);} else if ("city".equals(type)) {result = Utility.handleCitiesResponse(weatherDB,response, selectedProvince);} else if ("county".equals(type)) {result = Utility.handleCountiesResponse(weatherDB,response, selectedCity);}if (result) {// 通過runonUiMainThread方法返回主線程處理邏輯runOnUiThread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubcloseProgressDialog();if ("province".equals(type)) {queryProvinces();} else if ("city".equals(type)) {queryCities();} else if ("county".equals(type)) {queryCounties();}}});}}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {LogUtil.i("TAG", "-------------------->" + error);runOnUiThread(new Runnable() {@Overridepublic void run() { // TODO Auto-generated method// stub //closeProgressDialog();Toast.makeText(getApplicationContext(),"載入資料失敗!", Toast.LENGTH_SHORT).show();}});}});mQueue.add(stringRequest);
我們可以發現volley架構真的簡單了很多,不需要我們去設定一些HTTP的通訊屬性以及一些回調方法,讓我們只用去關心如何處理返回的資料即可,那麼下面我們來逐條解析一下volley三步操作的每一步。
RequestQueue mQueue = Volley.newRequestQueue(context);
第一步首先需要擷取到一個RequestQueue對象,注意這裡拿到的RequestQueue是一個請求隊列對象,它可以緩衝所有的HTTP請求,然後按照一定的演算法並發地發出這些請求。
StringRequest stringRequest = new StringRequest(address, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.d("TAG", response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); 第二步發送http請求,其中要傳入三個參數,第一個就是訪問的目標網站的網址,第二個是成功回調得到資料後的方法,第三個是失敗回調得到資料的方法,是不是很簡單,省去了我們建立介面的過程。
mQueue.add(stringRequest);
最後,將這個StringRequest對象添加到RequestQueue裡面就可以了,大功完成!好的,這一節課的內容就講到這裡,也希望大家能繼續支援該系列的博文,你們的支援是我寫下去的最大動力!今天的網路通訊的內容就到此結束,下一篇博文也會很快跟大家見面的。 下面是該應用的Git開源地址,https://github.com/melhc/SimpleWeather