摘要:需要注意的是回調并不是在線程。也可以通過來同時取消多個請求。在開始創建的時候配置好,在請求網絡的時候用將請求的結果回調給線程。最后調用這個的方法請求成功使用起來簡單多了,而且請求結果回調是在線程的。
前言
講完了Volley,我們接下來看看目前比較火的網絡框架OkHttp, 它處理了很多網絡疑難雜癥:會從很多常用的連接問題中自動恢復。如果您的服務器配置了多個IP地址,當第一個IP連接失敗的時候,OkHttp會自動嘗試下一個IP,此外OkHttp還處理了代理服務器問題和SSL握手失敗問題。
1.使用前準備eclipse引入jar包地址:
okhttp-2.7.5.jar
okio-1.7.0.jar
Android Studio 配置gradle:
compile "com.squareup.okhttp:okhttp:2.7.5" compile "com.squareup.okio:okio:1.7.0"2.異步GET請求
最簡單的get請求,老規矩請求百度:
private void getAsynHttp() { //創建okHttpClient對象 OkHttpClient mOkHttpClient = new OkHttpClient(); final Request request = new Request.Builder() .url("http://www.baidu.com") .build(); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(final Response response) throws IOException { String str = response.body().string(); Log.i("wangshu", str); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplication(), "請求成功", Toast.LENGTH_SHORT).show(); } }); } }); }
運行程序log打印出來的是百度首頁的html文件,基本的步驟很簡單,就是創建OkHttpClient、Request和Call,最后調用Call的enqueue()方法。但是每次這么寫肯定是很麻煩,肯定是要進行封裝的。需要注意的是onResponse回調并不是在UI線程。
3.同步GET請求private String getSyncHttp() throws IOException{ OkHttpClient mOkHttpClient = new OkHttpClient(); //創建請求Request final Request request = new Request.Builder() .url("http://www.baidu.com") .build(); Call call = mOkHttpClient.newCall(request); Response mResponse=call.execute(); if (mResponse.isSuccessful()) { return mResponse.body().string(); } else { throw new IOException("Unexpected code " + mResponse); } }
同步Get請求和異步調用區別就是調用了call的execute()方法。
4.異步POST請求private void postAsynHttp() { OkHttpClient mOkHttpClient = new OkHttpClient(); RequestBody formBody = new FormEncodingBuilder() .add("size", "10") .build(); Request request = new Request.Builder() .url("http://api.1-blog.com/biz/bizserver/article/list.do") .post(formBody) .build(); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(Response response) throws IOException { String str = response.body().string(); Log.i("wangshu", str); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show(); } }); } }); }
post與get不同的就是要要創建RequestBody并傳進Request中,同樣onResponse回調不是在UI線程。
5.請求緩存設置首先我們設置緩存路徑和大小并設置給OkHttpClient:
mOkHttpClient = new OkHttpClient(); File sdcache = getExternalCacheDir(); int cacheSize = 10 * 1024 * 1024; mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
接下來異步GET請求baidu:
private void getAsynHttp() { //創建請求Request final Request request = new Request.Builder() .url("http://www.baidu.com") .build(); Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(final Response response) throws IOException { if (null != response.cacheResponse()) { String str = response.cacheResponse().toString(); Log.i("wangshu", "cache---" + str); } else { response.body().string(); String str=response.networkResponse().toString(); Log.i("wangshu", "network---" + str); } runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show(); } }); } }); }
第一次請求會請求網絡得到數據,第二次以及后面的請求則會從緩存中取出數據:
當然也有種情況是有的請求每次都需要最新的數據,則在創建Request,來設置cacheControl為“CacheControl.FORCE_NETWORK”,用來表示請求會一直請求網絡得到數據:
final Request request = new Request.Builder() .url("http://www.baidu.com") .cacheControl(CacheControl.FORCE_NETWORK) .build();
運行程序結果為:
6.設置超時時間另外我們也需要設置超時的時間用來處理各種網絡超時的情況,超時的原因可能是網絡問題也可能是服務器響應慢等問題,OkHttp當然不會忽略這一點,它支持連接、讀取和寫入超時的時間設置:
mOkHttpClient = new OkHttpClient(); mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS); mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS);7.取消請求
使用call.cancel()可以立即停止掉一個正在執行的call。如果一個線程正在寫請求或者讀響應,將會引發IOException。當用戶離開一個應用時或者跳到其他界面時,使用Call.cancel()可以節約網絡資源,另外不管同步還是異步的call都可以取消。
也可以通過tags來同時取消多個請求。當你構建一請求時,使用RequestBuilder.tag(tag)來分配一個標簽。之后你就可以用OkHttpClient.cancel(tag)來取消所有帶有這個tag的call。
為了模擬這個場景我們首先創建一個定時的線程池:
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
接下來的代碼為:
private void cancel(){ final Request request = new Request.Builder() .url("http://www.baidu.com") .cacheControl(CacheControl.FORCE_NETWORK) .build(); Call call=null; call = mOkHttpClient.newCall(request); final Call finalCall = call; //100毫秒后取消call executor.schedule(new Runnable() { @Override public void run() { finalCall.cancel(); } }, 100, TimeUnit.MILLISECONDS); call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(final Response response) { if (null != response.cacheResponse()) { String str = response.cacheResponse().toString(); Log.i("wangshu", "cache---" + str); } else { try { response.body().string(); } catch (IOException e) { Log.i("wangshu", "IOException"); e.printStackTrace(); } String str = response.networkResponse().toString(); Log.i("wangshu", "network---" + str); } } }); Log.i("wangshu", "是否取消成功"+call.isCanceled()); }
100毫秒后調用call.cancel(),為了能讓請求耗時,我們設置每次請求都要請求網絡,運行程序并且不斷的快速點擊發送請求按鈕:
很明顯每次cancel()都失敗了,仍舊成功的訪問了網絡,在cancel()時已經有讀寫操作了所以會報IOException。每隔100毫秒來調用call.cancel()顯然時間間隔太長,我們設置為1毫秒并不斷的快速的點擊發送請求按鈕:
沒有請求網絡的log,幾乎每次都取消成功了。
8.關于封裝如果每次請求網絡都需要寫重復的代碼絕對是令人頭疼的,網上也有很多對OkHttp封裝的優秀開源項目,功能也非常強大,封裝的意義就在于更加方便的使用,具有拓展性,但是對OkHttp封裝最需要解決的是以下的兩點:
避免重復代碼調用
將請求結果回調改為UI線程
根據以上兩點,我們也簡單封裝一下,在此只是舉個例子,如果想要使用OkHttp封裝的開源庫,推薦使用OkHttpFinal。
首先呢我們寫一個抽象類用于請求回調:
public abstract class ResultCallback{ public abstract void onError(Request request, Exception e); public abstract void onResponse(Response response); }
接下來封裝OkHttp,并實現了異步GET請求:
public class OkHttpEngine { private static OkHttpEngine mInstance; private OkHttpClient mOkHttpClient; private Handler mHandler; public static OkHttpEngine getInstance() { if (mInstance == null) { synchronized (OkHttpEngine.class) { if (mInstance == null) { mInstance = new OkHttpEngine(); } } } return mInstance; } private OkHttpEngine() { mOkHttpClient = new OkHttpClient(); mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS); mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS); mHandler = new Handler(); } public OkHttpEngine setCache(Context mContext) { File sdcache = mContext.getExternalCacheDir(); int cacheSize = 10 * 1024 * 1024; mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize)); return mInstance; } /** * 異步get請求 * @param url * @param callback */ public void getAsynHttp(String url, ResultCallback callback) { final Request request = new Request.Builder() .url(url) .build(); Call call = mOkHttpClient.newCall(request); dealResult(call, callback); } private void dealResult(Call call, final ResultCallback callback) { call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { sendFailedCallback(request, e, callback); } @Override public void onResponse(final Response response) throws IOException { sendSuccessCallback(response, callback); } private void sendSuccessCallback(final Response object, final ResultCallback callback) { mHandler.post(new Runnable() { @Override public void run() { if (callback != null) { callback.onResponse(object); } } }); } private void sendFailedCallback(final Request request, final Exception e, final ResultCallback callback) { mHandler.post(new Runnable() { @Override public void run() { if (callback != null) callback.onError(request, e); } }); } }); } }
原理很簡單就是,寫一個雙重檢查模式的單例,不了解雙重檢查模式的請查看設計模式之單例模式的七種寫法這篇文章。在開始創建的時候配置好OkHttpClient,在請求網絡的時候用Handler將請求的結果回調給UI線程。
最后調用這個OkHttpEngine的getAsynHttp()方法:
OkHttpEngine.getInstance().getAsynHttp("http://www.baidu.com", new ResultCallback() { @Override public void onError(Request request, Exception e) { } @Override public void onResponse(Response response) { String str = response.networkResponse().toString(); Log.i("wangshu", str); Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show(); } });
使用起來簡單多了,而且請求結果回調是在UI線程的。下一篇我們會講到OkHttp3,來看看它與OkHttp2.x之間的使用方式上有什么區別。
github源碼下載
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70589.html
摘要:使用前準備配置添加網絡權限異步請求慣例,請求百度可以省略,默認是請求請求成功與版本并沒有什么不同,比較郁悶的是回調仍然不在線程。 前言 上一篇介紹了OkHttp2.x的用法,這一篇文章我們來對照OkHttp2.x版本來看看,OkHttp3使用起來有那些變化。當然,看這篇文章前建議看一下前一篇文章Android網絡編程(五)OkHttp2.x用法全解析。 1.使用前準備 Android ...
摘要:異步請求當正在運行的異步請求隊列中的數量小于并且正在運行的請求主機數小于時則把請求加載到中并在線程池中執行,否則就再入到中進行緩存等待。通常情況下攔截器用來添加,移除或者轉換請求或者響應的頭部信息。 前言 學會了OkHttp3的用法后,我們當然有必要來了解下OkHttp3的源碼,當然現在網上的文章很多,我仍舊希望我這一系列文章篇是最簡潔易懂的。 1.從請求處理開始分析 首先OKHttp...
摘要:前言想必很多人都用過,為了建立網絡編程的知識體系,是必須要講的知識點,所以我這里有必要再次介紹一下的使用。簡介在年大會上推出了一個新的網絡通信框架。在使用前請下載庫并放在目錄下并到工程中。 前言 Volley想必很多人都用過,為了建立網絡編程的知識體系,Volley是必須要講的知識點,所以我這里有必要再次介紹一下Volley的使用。 1.Volley簡介 在2013年Google I/...
閱讀 798·2023-04-25 22:57
閱讀 3051·2021-11-23 10:03
閱讀 614·2021-11-22 15:24
閱讀 3156·2021-11-02 14:47
閱讀 2901·2021-09-10 11:23
閱讀 3115·2021-09-06 15:00
閱讀 3936·2019-08-30 15:56
閱讀 3322·2019-08-30 15:52