1. 程式人生 > >Android 網路程式設計(5): OkHttp2.x用法全解析

Android 網路程式設計(5): OkHttp2.x用法全解析

前言

講完了Volley,我們接下來看看目前比較火的網路框架OkHttp, 它處理了很多網路疑難雜症:會從很多常用的連線問題中自動恢復。如果您的伺服器配置了多個IP地址,當第一個IP連線失敗的時候,OkHttp會自動嘗試下一個IP,此外OkHttp還處理了代理伺服器問題和SSL握手失敗問題。

1.使用前準備

Android Studio 配置gradle:

Java
12 compile'com.squareup.okhttp:okhttp:2.7.5'compile'com.squareup.okio:okio:1.7.0'

2.非同步GET請求

最簡單的get請求,老規矩請求百度:

Java
12345678910111213141516171819202122232425 privatevoidgetAsynHttp(){//建立okHttpClient物件OkHttpClient mOkHttpClient=newOkHttpClient();finalRequest request=newRequest.Builder().url("http://www.baidu.com").build();Call call=mOkHttpClient.newCall(request);call.enqueue(
newCallback(){@OverridepublicvoidonFailure(Request request,IOExceptione){}@OverridepublicvoidonResponse(finalResponse response)throwsIOException{Stringstr=response.body().string();Log.i("wangshu",str);runOnUiThread(newRunnable(){@Overridepublicvoidrun(){Toast.makeText(getApplication(),"請求成功",Toast.LENGTH_SHORT).show();}});}});}

執行程式log打印出來的是百度首頁的html檔案,基本的步驟很簡單,就是建立OkHttpClient、Request和Call,最後呼叫Call的enqueue()方法。但是每次這麼寫肯定是很麻煩,肯定是要進行封裝的。需要注意的是onResponse回撥並不是在UI執行緒。

3.同步GET請求

Java
1234567891011121314 privateStringgetSyncHttp()throwsIOException{OkHttpClient mOkHttpClient=newOkHttpClient();//建立請求RequestfinalRequest request=newRequest.Builder().url("http://www.baidu.com").build();Call call=mOkHttpClient.newCall(request);Response mResponse=call.execute();if(mResponse.isSuccessful()){returnmResponse.body().string();}else{thrownewIOException("Unexpected code "+mResponse);}}

同步Get請求和非同步呼叫區別就是呼叫了call的execute()方法。

4.非同步POST請求

Java
123456789101112131415161718192021222324252627282930 privatevoidpostAsynHttp(){OkHttpClient mOkHttpClient=newOkHttpClient();RequestBody formBody=newFormEncodingBuilder().add("size","10").build();Request request=newRequest.Builder().url("http://api.1-blog.com/biz/bizserver/article/list.do").post(formBody).build();Call call=mOkHttpClient.newCall(request);call.enqueue(newCallback(){@OverridepublicvoidonFailure(Request request,IOExceptione){}@OverridepublicvoidonResponse(Response response)throwsIOException{Stringstr=response.body().string();Log.i("wangshu",str);runOnUiThread(newRunnable(){@Overridepublicvoidrun(){Toast.makeText(getApplicationContext(),"請求成功",Toast.LENGTH_SHORT).show();}});}});}

post與get不同的就是要要建立RequestBody並傳進Request中,同樣onResponse回撥不是在UI執行緒。

5.請求快取設定

首先我們設定快取路徑和大小並設定給OkHttpClient:

Java
1234 mOkHttpClient=newOkHttpClient();File sdcache=getExternalCacheDir();intcacheSize=10*1024*1024;mOkHttpClient.setCache(newCache(sdcache.getAbsoluteFile(),cacheSize));

接下來非同步GET請求baidu:

Java
123456789101112131415161718192021222324252627282930 privatevoidgetAsynHttp(){//建立請求RequestfinalRequest request=newRequest.Builder().url("http://www.baidu.com").build();Call call=mOkHttpClient.newCall(request);call.enqueue(newCallback(){@OverridepublicvoidonFailure(Request request,IOExceptione){}@OverridepublicvoidonResponse(finalResponse response)throwsIOException{if(null!=response.cacheResponse()){Stringstr=response.cacheResponse().toString();Log.i("wangshu","cache---"+str);}else{response.body().string();Stringstr=response.networkResponse().toString();Log.i("wangshu","network---"+str);}runOnUiThread(newRunnable(){@Overridepublicvoidrun(){Toast.makeText(getApplicationContext(),"請求成功",Toast.LENGTH_SHORT).show();}});}});}

第一次請求會請求網路得到資料,第二次以及後面的請求則會從快取中取出資料:

20160416174053791

當然也有種情況是有的請求每次都需要最新的資料,則在建立Request,來設定cacheControl為“CacheControl.FORCE_NETWORK”,用來表示請求會一直請求網路得到資料:

Java
1234 finalRequest request=newRequest.Builder().url("http://www.baidu.com").cacheControl(CacheControl.FORCE_NETWORK).build();

執行程式結果為:

20160416173919961

6.設定超時時間

另外我們也需要設定超時的時間用來處理各種網路超時的情況,超時的原因可能是網路問題也可能是伺服器響應慢等問題,OkHttp當然不會忽略這一點,它支援連線、讀取和寫入超時的時間設定:

Java
1234 mOkHttpClient=newOkHttpClient();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。

為了模擬這個場景我們首先建立一個定時的執行緒池:

Java
1 privateScheduledExecutorService executor=Executors.newScheduledThreadPool(1);

接下來的程式碼為:

Java