okHttp

楓葉

okHttp是一個第三方的庫被Square開發(fā)用來發(fā)送和接收接觸的Http request 和response仔夺。它建立在Okio庫上。Okio庫試圖通過共享內(nèi)存池(shared memory pool)構(gòu)建相比標(biāo)準(zhǔn)java I/O庫狮腿,更有效的讀寫數(shù)據(jù)。它還是Retorfit的底層庫提供更類型安全的消費REST-based API猜旬。

okHttp庫事實上提供HttpUrlConnection的接口實現(xiàn)桩砰。底層HttpUrlConnection類可能是oKHttp庫的底層實現(xiàn)。然而在oKHttp中的提供了一個分離的API凌节,事發(fā)送以及接收網(wǎng)絡(luò)請求更加容易钦听。

OkHttp v2.4也提供了一個內(nèi)部管理URL的升級方法,替代java.net.URL倍奢,java.net.URI朴上,或者android.net.Uri類,它提供了一個新的HttpUrl類卒煞,提供更加方便的方法獲取Http端口痪宰,URL解析,和處理URL字符串畔裕。


SetUp

確保在AndroidManifest.xml文件中打開了使用網(wǎng)絡(luò)權(quán)限:

<uses-permission android:name="android.permission.INTERNET"/>

將下列行添加到你的app/build.gradle文件中:

compile  'com.squareup.okhttp3:okhttp:3.3.0'

Note:如果將okHttp升級衣撬,導(dǎo)入也需要修改為:

import com.squareup.okhttp.XXXX to import okhttp3.XXXX

Note:如果你打算在OkHttp3中使用Picasso,確保添加基礎(chǔ)下載扮饶。這個變化是必須的直到下個版本的Picasso

dependencies{
  compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
}

Sending and Receiving Network Requests

首先 我們初始化okHttpclient 并且建立一個 Request實例

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("http://publicobject.com/helloworld.txt")
  .build()

如果需要添加其他的查詢參數(shù)具练,這個okHttp庫提供HttpUrl類可以方便的構(gòu)造URL:

HttpUrl.Builder urlBuilder = HttpUrl.parse("https://ajax.googleapis.com/ajax/services/search/images").newBuilder();
urlBuilder.addQueryParameter("v", "1.0")甜无;
urlBuilder.addQueryParameter("q", "android")扛点;
urlBuilder.addQueryParameter("rsz", "8");
Sring url = urlBuilder.build().toString()岂丘;
Request request = new Request.Builder()
  .url(url)
  .build();

如果有任何查詢效驗參數(shù)陵究,request可以添加效驗頭部:

Request request = new Request.Builder()
    .header("Authorization", "token abcd")
    .url("https://api.github.com/users/codepath")
    .build();

Http Post Json

public static final MediaType JSON = MediaType.parse("application/json; charset = utf-8")
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException{
    RequestBody body = RequestBody.create(JSON, json);
    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);
      }
}

Htttp Post 提交鍵值對
使用FormEncodingBuilder 來構(gòu)建和HTML <form>標(biāo)簽相同效果的請求體奥帘,鍵值對將使用一種HTML兼容形式的URL編碼來進行編碼畔乙。

OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException{
    RequestBody formBody = new FormEncodingBuilder()
      .add("platform", "android")
      .add("name", "bug")
      .add("subject", "XXXXXXXXX")
      .build();
    Request  request = new Request.Builder()
      .url(url)
      .post(formBody)
      .build();
    Response response = client.newCall(request).execute();
    if (response,isSuccessful()){
      return response.body().string();
    }else{
      throw new IOException("Unexpected code" + response)
    }
}

Post 方式提交流
以流的方式POST提交請求體,請求體的內(nèi)容由i流寫入產(chǎn)成翩概。

public static final MediaType MEDIA_TYPE_MARKDOWN
    = MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
    RequestBody requestBody = new RequsetBody(){
        @Override 
        public MediaType contentType(){
            return MEDIA_TYPE_MARKDOWN;
        }
        @Override
        public void writeTo(BufferedSink sink) throws IOException{
          sink.writeUtf8("Numbers\n");
          sink.writeUtf8("------------\n");
          for (int i = 2; i <=997; i++)
          {
            sink.writeUtf8(String.format("* %s = %s\n", i, factor(i)));
          }
        }
        private String factor(int n)
        {
          for(int i = 2 ; i< n; i++)
          {
            int x = n / i;
            if(x * i == n)
              return factor(x) + " x "  + i;
          }
          return Integer.toString(n);
        }
    };  
    Request request = new Request.Builder()
      .url("[https://api.github.com/markdown/raw](https://api.github.com/markdown/raw)")
      .post(requestBody)
      .build();
}

Post 方式提交文件

public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
private void run() throws Exception{
    File file = new File("README.md");
    Request request = new Request.Builder()
        .url("[https://api.github.com/markdown/raw](https://api.github.com/markdown/raw)")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
        .build();
}

Synchronous Network Calls

我們創(chuàng)建Call實例并且分發(fā)網(wǎng)絡(luò)同步請求:

Response response = client.newCall(requset).execute()牲距;

由于Android不允許主線程中進行網(wǎng)絡(luò)調(diào)用返咱,如果你在分離的線程或者后臺服務(wù),你可以使用synchronous調(diào)用牍鞠。你也可以使用AsyncTask 用于輕量級的網(wǎng)絡(luò)調(diào)用咖摹。


Asynchronous Network Calls

我們也可以創(chuàng)建一個異步網(wǎng)絡(luò)調(diào)用,通過創(chuàng)建一個Call對象难述。通過使用enqueue()方法并且傳入一個匿名Callback對象萤晴,并且實現(xiàn)onFailure()和onResponse()方法

client.newCall(request).enqueue(new Callback(){
    @Override
    public void onFailure(Call call,IOException e)
    {
        e.printStackTrace()胁后;
    }
    @Override
    public void onResponse(Call call店读,final Response response) throws IOException
    {
         if(!response.isSuccessful()){
              throw new IOException("Unexpected code " +  response);
          }
    }
})

OkHttp 通常創(chuàng)建一個新的工作線程分發(fā)網(wǎng)絡(luò)請求攀芯,并且使用相同的線程去處理響應(yīng)屯断。OkHttp建立的目的是作為一個Java庫,并不處理Android框架中的限制(view 只允許在主線程中更新)侣诺。如果你需要更新任何view殖演,你需要runOnUiThread()方法,并且將結(jié)果返回至主線程年鸳。

client.newCall(request).enqueue(new Callback() {
    @Override 
    public void onResponse(Call call, final Response response) throws IOException {
      final String responseData = response.body().string(); 
      MainActivity.this.runOnUiThread(new Runnable() {
         @Override 
         public void run() {
               try { 
                    TextView myTextView = (TextView)findViewById(R.id.myTextView);
                    myTextView.setText(responseData); 
               } catch (IOException e) {
                     e.printStackTrace(); 
               }
        }
    }
}
});

Processing Network Response

假設(shè)Request沒有被取消并且沒有connect問題趴久,并且 onResponse()方法將被調(diào)用。他傳遞一個 Response 實例搔确,并且可以被用來查看狀態(tài)碼彼棍,響應(yīng)體,以及任何相應(yīng)頭將會被返回膳算。調(diào)用 isSuccessful() 對應(yīng)實例碼相應(yīng)狀態(tài)碼 2XX (i.e 200, 201)

if (!response.isSuccessful()){
    throw new IOException("Unexcepted code" + response);
}

響應(yīng)頭被作為一個列表返回:

Headers responseHeaders = response.header();
for (int i = 0; i < responseHeaders.size(); i++)
{
    Log.d("DEBUG", responseHeaders.name(i) + ":" + responseHeaders.value(i));
}

我們也可以獲得響應(yīng)數(shù)據(jù)座硕,通過調(diào)用 response.body()并且調(diào)用 string() 方法去讀取整個playload,注意 response.body()只可以被調(diào)用一次畦幢,并且應(yīng)該在后臺線程中調(diào)用坎吻。

Log.d("DEBUG", response.body().string());

Processing JSON data
我們調(diào)用Github API ,將會返回JSON 數(shù)據(jù):

Request request = new Request.Builder()
    .url("https://api.github.com/users/codepath")
    .build();

我們可以解析JOSN 數(shù)據(jù) 通過JSONobject 或者 JSONArray 類宇葱,這取決于響應(yīng)數(shù)據(jù)類型:

client.newCall(request).enqueue(new Callback(){
    @Override
    public void onResponse(Call call, final Response response) throws IOException{
        try{
            String responseData = response.body().string();
            JSONObject json = new JSONObject(responseData);
            final String owner = json.getString("name");
        }catch (JSONException e )
        {
        }
    }
});

Processing JSON data with Gson
注意 sting() 方法作用在響應(yīng)體將會將所有的數(shù)據(jù)加載到內(nèi)存中瘦真。為了更加合理的使用內(nèi)存,推薦響應(yīng)進程通過 使用charStream()代替
為了使用Gson庫黍瞧,我們首先要聲明類匹配JSON 響應(yīng):

static class GitUser{
    String name;
    String url;
    int id;
}

我們可以使用使用Gson解析器诸尽,將數(shù)據(jù)轉(zhuǎn)換到j(luò)ava模型中:

final Gson gson = new Gson();
client.newCall(request).enqueue(new Callback() {
      @Override
      public void onResponse(Call call, final Response response) throws IOException {
           GitUser user = gson.fromJson(response.body().charStream(), GitUser.class);
      }
}

Caching Network Responses
我們可以創(chuàng)建OkHttpClient并且配置cache緩存:

int cacheSize = 10 * 1024 * 1024 ;     // 10 Mib
Cache cache = new Cache(getApplication().getCacheDir()印颤,cacheSize)您机;
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();

我們可以控制是否取回緩存相應(yīng)通過在request上設(shè)置cacheControl屬性。如過我們希望獲取緩存中的響應(yīng)數(shù)據(jù),我們可以向下面一樣配置Request實例

Request request = new Request.Builder()
    .url("http://publicobject.com/helloworld.txt")
    .cacheControl(new CacheControl.Builder().onlyIfCached().build())
    .build();

我們可以設(shè)置request請求響應(yīng)response 使用noCache()

.cacheControl(new CacheControl.Builder().noCache().build())

我們也可以標(biāo)明響應(yīng)緩存的最大生存周期

.cacheControl(new CacheControl.Builder().maxStale(365际看,TimeUnit.DAYS).build())

為了取回cache相應(yīng)咸产,我們可以簡單的在響應(yīng)實例上調(diào)用cacheResponse()

Call call = client.newCall(request);
call.enqueue(new Callback(){
    @Override
    public void onFailure(Call call, IOException e){
    }
    @Override
    public void onResponse(Call call, final Response response) throws IOException
    {
        final Response text = response.cacheResponse();
        if(text != null){
            Log.d("here", text.toString());
        }
    }
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仲闽,隨后出現(xiàn)的幾起案子脑溢,更是在濱河造成了極大的恐慌,老刑警劉巖赖欣,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屑彻,死亡現(xiàn)場離奇詭異,居然都是意外死亡顶吮,警方通過查閱死者的電腦和手機社牲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悴了,“玉大人搏恤,你說我怎么就攤上這事∪觅鳎” “怎么了挑社?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵陨界,是天一觀的道長巡揍。 經(jīng)常有香客問我,道長菌瘪,這世上最難降的妖魔是什么腮敌? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮俏扩,結(jié)果婚禮上糜工,老公的妹妹穿的比我還像新娘。我一直安慰自己录淡,他們只是感情好捌木,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嫉戚,像睡著了一般刨裆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彬檀,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天帆啃,我揣著相機與錄音,去河邊找鬼窍帝。 笑死努潘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疯坤,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼报慕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了压怠?” 一聲冷哼從身側(cè)響起卖子,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刑峡,沒想到半個月后洋闽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡突梦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年诫舅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宫患。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡刊懈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娃闲,到底是詐尸還是另有隱情虚汛,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布皇帮,位于F島的核電站卷哩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏属拾。R本人自食惡果不足惜将谊,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渐白。 院中可真熱鬧尊浓,春花似錦、人聲如沸纯衍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽襟诸。三九已至瓦堵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間励堡,已是汗流浹背谷丸。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留应结,地道東北人刨疼。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓泉唁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揩慕。 傳聞我的和親對象是個殘疾皇子亭畜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)迎卤,斷路器拴鸵,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 參考Android網(wǎng)絡(luò)請求心路歷程Android Http接地氣網(wǎng)絡(luò)請求(HttpURLConnection) 一...
    合肥黑閱讀 21,274評論 7 63
  • OkHttp使用完全教程 標(biāo)簽 : Http請求, 類庫blog : http://blog.csdn.net/o...
    oncealong閱讀 170,239評論 27 459
  • 這篇文章主要講 Android 網(wǎng)絡(luò)請求時所使用到的各個請求庫的關(guān)系,以及 OkHttp3 的介紹蜗搔。(如理解有誤劲藐,...
    小莊bb閱讀 1,157評論 0 4
  • Okhttp使用指南與源碼分析 標(biāo)簽(空格分隔): Android 使用指南篇# 為什么使用okhttp### A...
    背影殺手不太冷閱讀 8,150評論 2 119