Android使用http協(xié)議與服務(wù)器通信的實(shí)例
網(wǎng)上介紹Android上http通信的文章很多,不過(guò)大部分只給出了實(shí)現(xiàn)代碼的片段,一些注意事項(xiàng)和如何設(shè)計(jì)一個(gè)合理的類用來(lái)處理所有的http請(qǐng)求以及返回結(jié)果,一般都不會(huì)提及。因此,自己對(duì)此做了些總結(jié),給出了我的一個(gè)解決方案。
首先,需要明確一下http通信流程,Android目前提供兩種http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于發(fā)送或接收流式數(shù)據(jù),因此比較適合上傳/下載文件,HttpClient相對(duì)來(lái)講更大更全能,但是速度相對(duì)也要慢一點(diǎn)。在此只介紹HttpClient的通信流程:
1.創(chuàng)建HttpClient對(duì)象,改對(duì)象可以用來(lái)多次發(fā)送不同的http請(qǐng)求
2.創(chuàng)建HttpPost或HttpGet對(duì)象,設(shè)置參數(shù),每發(fā)送一次http請(qǐng)求,都需要這樣一個(gè)對(duì)象
3.利用HttpClient的execute方法發(fā)送請(qǐng)求并等待結(jié)果,該方法會(huì)一直阻塞當(dāng)前線程,直到返回結(jié)果或拋出異常。
4.針對(duì)結(jié)果和異常做相應(yīng)處理
根據(jù)上述流程,發(fā)現(xiàn)在設(shè)計(jì)類的時(shí)候,有幾點(diǎn)需要考慮到:
1.HttpClient對(duì)象可以重復(fù)使用,因此可以作為類的靜態(tài)變量
2.HttpPost/HttpGet對(duì)象一般無(wú)法重復(fù)使用(如果你每次請(qǐng)求的參數(shù)都差不多,也可以重復(fù)使用),因此可以創(chuàng)建一個(gè)方法用來(lái)初始化,同時(shí)設(shè)置一些需要上傳到服務(wù)器的資源
3.目前Android不再支持在UI線程中發(fā)起Http請(qǐng)求,實(shí)際上也不該這么做,因?yàn)檫@樣會(huì)阻塞UI線程。因此還需要一個(gè)子線程,用來(lái)發(fā)起Http請(qǐng)求,即執(zhí)行execute方法
4.不同的請(qǐng)求對(duì)應(yīng)不同的返回結(jié)果,對(duì)于如何處理返回結(jié)果(一般來(lái)說(shuō)都是解析json&更新UI),需要有一定的自由度。
5.最簡(jiǎn)單的方法是,每次需要發(fā)送http請(qǐng)求時(shí),開(kāi)一個(gè)子線程用于發(fā)送請(qǐng)求,子線程中接收到結(jié)果或拋出異常時(shí),根據(jù)情況給UI線程發(fā)送message,最后在UI線程的handler的handleMessage方法中做結(jié)果解析和UI更新。這么寫雖然簡(jiǎn)單,但是UI線程和Http請(qǐng)求的耦合度很高,而且代碼比較散亂、丑陋。
基于上述幾點(diǎn)原因,我設(shè)計(jì)了一個(gè)PostRequest類,用于滿足我的http通信需求。我只用到了Post請(qǐng)求,如果你需要Get請(qǐng)求,也可以改寫成GetRequest
package com.handspeaker.network; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.net.ConnectivityManager; import android.os.Handler; import android.util.Log; /** * * 用于封裝&簡(jiǎn)化http通信 * */ public class PostRequest implements Runnable { private static final int NO_SERVER_ERROR=1000; //服務(wù)器地址 public static final String URL = "fill your own url"; //一些請(qǐng)求類型 public final static String ADD = "/add"; public final static String UPDATE = "/update"; public final static String PING = "/ping"; //一些參數(shù) private static int connectionTimeout = 60000; private static int socketTimeout = 60000; //類靜態(tài)變量 private static HttpClient httpClient=new DefaultHttpClient(); private static ExecutorService executorService=Executors.newCachedThreadPool(); private static Handler handler = new Handler(); //變量 private String strResult; private HttpPost httpPost; private HttpResponse httpResponse; private OnReceiveDataListener onReceiveDataListener; private int statusCode; /** * 構(gòu)造函數(shù),初始化一些可以重復(fù)使用的變量 */ public PostRequest() { strResult = null; httpResponse = null; httpPost = new HttpPost(); } /** * 注冊(cè)接收數(shù)據(jù)監(jiān)聽(tīng)器 * @param listener */ public void setOnReceiveDataListener(OnReceiveDataListener listener) { onReceiveDataListener = listener; } /** * 根據(jù)不同的請(qǐng)求類型來(lái)初始化httppost * * @param requestType * 請(qǐng)求類型 * @param nameValuePairs * 需要傳遞的參數(shù) */ public void iniRequest(String requestType, JSONObject jsonObject) { httpPost.addHeader("Content-Type", "text/json"); httpPost.addHeader("charset", "UTF-8"); httpPost.addHeader("Cache-Control", "no-cache"); HttpParams httpParameters = httpPost.getParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, connectionTimeout); HttpConnectionParams.setSoTimeout(httpParameters, socketTimeout); httpPost.setParams(httpParameters); try { httpPost.setURI(new URI(URL + requestType)); httpPost.setEntity(new StringEntity(jsonObject.toString(), HTTP.UTF_8)); } catch (URISyntaxException e1) { e1.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * 新開(kāi)一個(gè)線程發(fā)送http請(qǐng)求 */ public void execute() { executorService.execute(this); } /** * 檢測(cè)網(wǎng)絡(luò)狀況 * * @return true is available else false */ public static boolean checkNetState(Activity activity) { ConnectivityManager connManager = (ConnectivityManager) activity .getSystemService(Context.CONNECTIVITY_SERVICE); if (connManager.getActiveNetworkInfo() != null) { return connManager.getActiveNetworkInfo().isAvailable(); } return false; } /** * 發(fā)送http請(qǐng)求的具體執(zhí)行代碼 */ @Override public void run() { httpResponse = null; try { httpResponse = httpClient.execute(httpPost); strResult = EntityUtils.toString(httpResponse.getEntity()); } catch (ClientProtocolException e1) { strResult = null; e1.printStackTrace(); } catch (IOException e1) { strResult = null; e1.printStackTrace(); } finally { if (httpResponse != null) { statusCode = httpResponse.getStatusLine().getStatusCode(); } else { statusCode=NO_SERVER_ERROR; } if(onReceiveDataListener!=null) { //將注冊(cè)的監(jiān)聽(tīng)器的onReceiveData方法加入到消息隊(duì)列中去執(zhí)行 handler.post(new Runnable() { @Override public void run() { onReceiveDataListener.onReceiveData(strResult, statusCode); } }); } } } /** * 用于接收并處理http請(qǐng)求結(jié)果的監(jiān)聽(tīng)器 * */ public interface OnReceiveDataListener { /** * the callback function for receiving the result data * from post request, and further processing will be done here * @param strResult the result in string style. * @param StatusCode the status of the post */ public abstract void onReceiveData(String strResult,int StatusCode); } }
代碼使用了觀察者模式,任何需要接收http請(qǐng)求結(jié)果的類,都要實(shí)現(xiàn)OnReceiveDataListener接口的抽象方法,同時(shí)PostRequest實(shí)例調(diào)用setOnReceiveDataListener方法,注冊(cè)該監(jiān)聽(tīng)器。完整調(diào)用步驟如下:
1.創(chuàng)建PostRequest對(duì)象,實(shí)現(xiàn)onReceiveData接口,編寫自己的onReceiveData方法
2.注冊(cè)監(jiān)聽(tīng)器
3.調(diào)用PostRequest的iniRequest方法,初始化本次request
4.調(diào)用PostRequest的execute方法
可能的改進(jìn):
1.如果需要多個(gè)觀察者,可以把只能注冊(cè)單個(gè)監(jiān)聽(tīng)器改為可以注冊(cè)多個(gè)監(jiān)聽(tīng)器,維護(hù)一個(gè)監(jiān)聽(tīng)器List。
2.如果需求比較簡(jiǎn)單,并希望調(diào)用流程更簡(jiǎn)潔,iniRequest和execute可以合并
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android使用WebSocket實(shí)現(xiàn)多人游戲
- SpringBoot webSocket實(shí)現(xiàn)發(fā)送廣播、點(diǎn)對(duì)點(diǎn)消息和Android接收
- Android中使用WebSocket實(shí)現(xiàn)群聊和消息推送功能(不使用WebView)
- android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信
- Android實(shí)現(xiàn)藍(lán)牙客戶端與服務(wù)器端通信示例
- Android編程之客戶端通過(guò)socket與服務(wù)器通信的方法
- python服務(wù)器與android客戶端socket通信實(shí)例
- android利用websocket協(xié)議與服務(wù)器通信
相關(guān)文章
21天學(xué)習(xí)android開(kāi)發(fā)教程之MediaPlayer
21天學(xué)習(xí)android開(kāi)發(fā)教程之MediaPlayer,MediaPlayer可以播放音頻和視頻,操作相對(duì)簡(jiǎn)單,感興趣的小伙伴們可以參考一下2016-02-02android自定義Camera實(shí)現(xiàn)錄像和拍照
這篇文章主要為大家詳細(xì)介紹了android自定義Camera實(shí)現(xiàn)錄像和拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android 8.0升級(jí)不跳轉(zhuǎn)應(yīng)用安裝頁(yè)面的解決方法
這篇文章主要為大家詳細(xì)介紹了Android 8.0升級(jí)不跳轉(zhuǎn)應(yīng)用安裝頁(yè)面的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Android依據(jù)名字通過(guò)反射獲取在drawable中的圖片
依據(jù)圖片的名字,通過(guò)反射獲取其在drawable中的ID,在根據(jù)此ID顯示圖片,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06Android Animation之TranslateAnimation(平移動(dòng)畫)
這篇文章主要為大家詳細(xì)介紹了Animation之TranslateAnimation平移動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Android實(shí)現(xiàn)QQ登錄界面遇到問(wèn)題及解決方法
本文給大家介紹android仿qq登錄界面的實(shí)現(xiàn)代碼,在實(shí)現(xiàn)此功能過(guò)程中遇到各種問(wèn)題,但是最終都順利解決,如果大家對(duì)android qq登錄界面實(shí)現(xiàn)方法感興趣的朋友一起學(xué)習(xí)吧2016-09-09正確在Flutter中添加webview實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了正確在Flutter中添加webview實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android使用popupWindow仿微信彈出框使用方法
這篇文章主要為大家詳細(xì)介紹了Android使用popupWindow仿微信彈出框使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09Jetpack?Compose慣性衰減動(dòng)畫AnimateDecay詳解
這篇文章主要為大家介紹了Jetpack?Compose慣性衰減動(dòng)畫AnimateDecay詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11