Android使用OKHttp包處理HTTP相關(guān)操作的基本用法講解
OKHttp是一款高效的HTTP客戶端,支持連接同一地址的鏈接共享同一個(gè)socket,通過(guò)連接池來(lái)減小響應(yīng)延遲,還有透明的GZIP壓縮,請(qǐng)求緩存等優(yōu)勢(shì)。(GitHub頁(yè):https://github.com/square/okhttp)
Android為我們提供了兩種HTTP交互的方式:HttpURLConnection 和 Apache HTTP Client,雖然兩者都支持HTTPS,流的上傳和下載,配置超時(shí),IPv6和連接池,已足夠滿足我們各種HTTP請(qǐng)求的需求。但更高效的使用HTTP 可以讓您的應(yīng)用運(yùn)行更快、更節(jié)省流量。而OkHttp庫(kù)就是為此而生。
OkHttp是一個(gè)高效的HTTP庫(kù):
- 支持 SPDY ,共享同一個(gè)Socket來(lái)處理同一個(gè)服務(wù)器的所有請(qǐng)求
- 如果SPDY不可用,則通過(guò)連接池來(lái)減少請(qǐng)求延時(shí)
- 無(wú)縫的支持GZIP來(lái)減少數(shù)據(jù)流量
- 緩存響應(yīng)數(shù)據(jù)來(lái)減少重復(fù)的網(wǎng)絡(luò)請(qǐng)求
- 會(huì)從很多常用的連接問題中自動(dòng)恢復(fù)。
如果您的服務(wù)器配置了多個(gè)IP地址,當(dāng)?shù)谝粋€(gè)IP連接失敗的時(shí)候,OkHttp會(huì)自動(dòng)嘗試下一個(gè)IP。OkHttp還處理了代理服務(wù)器問題和SSL握手失敗問題。
使用 OkHttp 無(wú)需重寫您程序中的網(wǎng)絡(luò)代碼。OkHttp實(shí)現(xiàn)了幾乎和java.net.HttpURLConnection一樣的API。如果您用了 Apache HttpClient,則OkHttp也提供了一個(gè)對(duì)應(yīng)的okhttp-apache 模塊。
引入
可以通過(guò)下載jar包直接導(dǎo)入工程地址
或者通過(guò)構(gòu)建的方式導(dǎo)入
MAVEN:
<dependency> <groupId>com.squareup.okhttp</groupId> <artifactId>okhttp</artifactId> <version>2.4.0</version> </dependency>
GRADLE:
compile 'com.squareup.okhttp:okhttp:2.4.0'
在向網(wǎng)絡(luò)發(fā)起請(qǐng)求的時(shí)候,我們最常用的就是GET和POST,下面就來(lái)看看如何使用
1. GET
在OKHttp,每次網(wǎng)絡(luò)請(qǐng)求就是一個(gè)Request,我們?cè)赗equest里填寫我們需要的url,header等其他參數(shù),再通過(guò)Request構(gòu)造出Call,Call內(nèi)部去請(qǐng)求參數(shù),得到回復(fù),并將結(jié)果告訴調(diào)用者。
package com.jackchan.test.okhttptest; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import com.squareup.okhttp.Cache; import com.squareup.okhttp.Callback; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.File; import java.io.IOException; public class TestActivity extends ActionBarActivity { private final static String TAG = "TestActivity"; private final OkHttpClient client = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); new Thread(new Runnable() { @Override public void run() { try { execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public void execute() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response = client.newCall(request).execute(); if(response.isSuccessful()){ System.out.println(response.code()); System.out.println(response.body().string()); } } }
這個(gè)是通過(guò)同步的方式去操作網(wǎng)絡(luò)請(qǐng)求,而android本身是不允許在UI線程做網(wǎng)絡(luò)請(qǐng)求操作的,因此我們需要自己開啟一個(gè)線程。
當(dāng)然,OKHttp也支持異步線程并且有回調(diào)返回,有了上面同步的基礎(chǔ),異步只要稍加改動(dòng)即可
private void enqueue(){ Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { } @Override public void onResponse(Response response) throws IOException { //NOT UI Thread if(response.isSuccessful()){ System.out.println(response.code()); System.out.println(response.body().string()); } } }); }
2、POST
說(shuō)完GET該介紹些如何使用POST,POST情況下我們一般需要傳入?yún)?shù),甚至一些header,傳入?yún)?shù)或者h(yuǎn)eader
比如傳入header
Request request = new Request.Builder() .url("https://api.github.com/repos/square/okhttp/issues") .header("User-Agent", "OkHttp Headers.java") .addHeader("Accept", "application/json; q=0.5") .addHeader("Accept", "application/vnd.github.v3+json") .build();
RequestBody formBody = new FormEncodingBuilder() .add("platform", "android") .add("name", "bug") .add("subject", "XXXXXXXXXXXXXXX") .build(); Request request = new Request.Builder() .url(url) .post(body) .build();
Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } else { throw new IOException("Unexpected code " + response); }
請(qǐng)求緩存
在網(wǎng)絡(luò)請(qǐng)求中,緩存技術(shù)是一項(xiàng)應(yīng)用比較廣泛的技術(shù),需要對(duì)請(qǐng)求過(guò)的網(wǎng)絡(luò)資源進(jìn)行緩存,而okhttp也支持這一技術(shù),也使用十分方便,前文漲經(jīng)常出現(xiàn)的OkHttpclient這個(gè)時(shí)候就要派送用場(chǎng)了。看下面代碼
package com.jackchan.test.okhttptest; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import com.squareup.okhttp.Cache; import com.squareup.okhttp.CacheControl; import com.squareup.okhttp.Call; import com.squareup.okhttp.Callback; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.File; import java.io.IOException; public class TestActivity extends ActionBarActivity { private final static String TAG = "TestActivity"; private final OkHttpClient client = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); File sdcache = getExternalCacheDir(); int cacheSize = 10 * 1024 * 1024; // 10 MiB client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize)); new Thread(new Runnable() { @Override public void run() { try { execute(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public void execute() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response1 = client.newCall(request).execute(); if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string(); System.out.println("Response 1 response: " + response1); System.out.println("Response 1 cache response: " + response1.cacheResponse()); System.out.println("Response 1 network response: " + response1.networkResponse()); Response response2 = client.newCall(request).execute(); if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string(); System.out.println("Response 2 response: " + response2); System.out.println("Response 2 cache response: " + response2.cacheResponse()); System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); } }

但有時(shí)候即使在有緩存的情況下我們依然需要去后臺(tái)請(qǐng)求最新的資源(比如資源更新了)這個(gè)時(shí)候可以使用強(qiáng)制走網(wǎng)絡(luò)來(lái)要求必須請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)
public void execute() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response1 = client.newCall(request).execute(); if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string(); System.out.println("Response 1 response: " + response1); System.out.println("Response 1 cache response: " + response1.cacheResponse()); System.out.println("Response 1 network response: " + response1.networkResponse()); request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build(); Response response2 = client.newCall(request).execute(); if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string(); System.out.println("Response 2 response: " + response2); System.out.println("Response 2 cache response: " + response2.cacheResponse()); System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); }
response2對(duì)應(yīng)的request變成
request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();

同樣的我們可以使用 FORCE_CACHE 強(qiáng)制只要使用緩存的數(shù)據(jù),但如果請(qǐng)求必須從網(wǎng)絡(luò)獲取才有數(shù)據(jù),但又使用了FORCE_CACHE 策略就會(huì)返回504錯(cuò)誤,代碼如下,我們?nèi)khttpclient的緩存,并設(shè)置request為FORCE_CACHE
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); File sdcache = getExternalCacheDir(); int cacheSize = 10 * 1024 * 1024; // 10 MiB //client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize)); new Thread(new Runnable() { @Override public void run() { try { execute(); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage().toString()); } } }).start(); } public void execute() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); Response response1 = client.newCall(request).execute(); if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1); String response1Body = response1.body().string(); System.out.println("Response 1 response: " + response1); System.out.println("Response 1 cache response: " + response1.cacheResponse()); System.out.println("Response 1 network response: " + response1.networkResponse()); request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); Response response2 = client.newCall(request).execute(); if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2); String response2Body = response2.body().string(); System.out.println("Response 2 response: " + response2); System.out.println("Response 2 cache response: " + response2.cacheResponse()); System.out.println("Response 2 network response: " + response2.networkResponse()); System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body)); }

網(wǎng)絡(luò)操作中,經(jīng)常會(huì)使用到對(duì)請(qǐng)求的cancel操作,okhttp的也提供了這方面的接口,call的cancel操作。使用Call.cancel()可以立即停止掉一個(gè)正在執(zhí)行的call。如果一個(gè)線程正在寫請(qǐng)求或者讀響應(yīng),將會(huì)引發(fā)IOException,同時(shí)可以通過(guò)Request.Builder.tag(Object tag)給請(qǐng)求設(shè)置一個(gè)標(biāo)簽,并使用OkHttpClient.cancel(Object tag)來(lái)取消所有帶有這個(gè)tag的call。但如果該請(qǐng)求已經(jīng)在做讀寫操作的時(shí)候,cancel是無(wú)法成功的,會(huì)拋出IOException異常。
public void canceltest() throws Exception { Request request = new Request.Builder() .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay. .build(); final long startNanos = System.nanoTime(); final Call call = client.newCall(request); // Schedule a job to cancel the call in 1 second. executor.schedule(new Runnable() { @Override public void run() { System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f); call.cancel(); System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f); } }, 1, TimeUnit.SECONDS); try { System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f); Response response = call.execute(); System.out.printf("call is cancel:" + call.isCanceled() + "%n"); System.out.printf("%.2f Call was expected to fail, but completed: %s%n", (System.nanoTime() - startNanos) / 1e9f, response); } catch (IOException e) { System.out.printf("%.2f Call failed as expected: %s%n", (System.nanoTime() - startNanos) / 1e9f, e); } }


- 使用OkHttp包在Android中進(jìn)行HTTP頭處理的教程
- Android的OkHttp包處理用戶認(rèn)證的代碼實(shí)例分享
- Android中Retrofit+OkHttp進(jìn)行HTTP網(wǎng)絡(luò)編程的使用指南
- Android M(6.x)使用OkHttp包解析和發(fā)送JSON請(qǐng)求的教程
- 使用Android的OkHttp包實(shí)現(xiàn)基于HTTP協(xié)議的文件上傳下載
- Android的HTTP擴(kuò)展包OkHttp中的緩存功能使用方法解析
- 詳解Android的OkHttp包編寫異步HTTP請(qǐng)求調(diào)用的方法
- Android的OkHttp包中的HTTP攔截器Interceptor用法示例
- Android第三方HTTP網(wǎng)絡(luò)支持包OkHttp的基礎(chǔ)使用教程
- Android App開發(fā)中HTTP擴(kuò)展包OkHttp的入門使用指南
- Android中使用OkHttp包處理HTTP的get和post請(qǐng)求的方法
- Android中的Retrofit+OkHttp+RxJava緩存架構(gòu)使用
- 詳解Android中使用OkHttp發(fā)送HTTP的post請(qǐng)求的方法
相關(guān)文章
Android中CheckBox復(fù)選框控件使用方法詳解
這篇文章主要為大家詳細(xì)介紹了Android中CheckBox復(fù)選框控件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android使用URLConnection提交請(qǐng)求的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android使用URLConnection提交請(qǐng)求的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android應(yīng)用中clearFocus方法調(diào)用無(wú)效的問題解決
clearFocus()主要用于清除EditText的焦點(diǎn),Android App開發(fā)中很多時(shí)候會(huì)發(fā)現(xiàn)其調(diào)用無(wú)效,帶著這個(gè)問題我們就來(lái)看一下本文主題、Android應(yīng)用中clearFocus方法調(diào)用無(wú)效的問題解決2016-05-05Android DatePicker和DatePickerDialog基本用法示例
這篇文章主要介紹了Android DatePicker和DatePickerDialog基本用法,實(shí)例分析了DatePicker和DatePickerDialog控件針對(duì)手機(jī)時(shí)間設(shè)置的相關(guān)技巧,需要的朋友可以參考下2016-06-06Android手勢(shì)ImageView三部曲 第一部
這篇文章主要為大家詳細(xì)介紹了Android手勢(shì)ImageView三部曲的第一部,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03