OkHttp之初學(xué)者使用(get盈匾、post之{RequestBody、FormBody毕骡、MultipartBody})

前言

Android網(wǎng)絡(luò)技術(shù)

  • android原生的使用http訪問(wèn)網(wǎng)絡(luò)【HttpUrlConnection削饵、HttpClient】
    官方推薦使用:HttpUrlConnection
    而對(duì)于HttpClient,6.0已經(jīng)廢除:HttpClient,api過(guò)多未巫,擴(kuò)展困難窿撬,難以維護(hù)
  • android-async-http。與volley一樣是異步網(wǎng)絡(luò)庫(kù)叙凡,但volley是封裝的httpUrlConnection劈伴,它是封裝的httpClient,而android平臺(tái)不推薦用HttpClient了握爷,所以這個(gè)庫(kù)已經(jīng)不適合android平臺(tái)了跛璧。
  • volley 非常適合去進(jìn)行數(shù)據(jù)量不大严里,但通信頻繁的網(wǎng)絡(luò)操作。不適合下載問(wèn)價(jià)一類(之前寫的關(guān)于新聞資訊的demo 用的就是volley網(wǎng)絡(luò)請(qǐng)求追城。請(qǐng)求頻繁刹碾,像流星)
  • 但是在開(kāi)元盛行的今天,有許多出色的網(wǎng)絡(luò)通信庫(kù)都可以代替原生的HttpUrlConnection
  • okthttp應(yīng)該是最出色的一個(gè)座柱,由square公司開(kāi)發(fā)迷帜,在接口封裝上做的簡(jiǎn)單易用,底層實(shí)現(xiàn)也是自成一派色洞,現(xiàn)在已經(jīng)成了廣大android開(kāi)發(fā)者首選的網(wǎng)絡(luò)通信庫(kù)戏锹。從Android4.4開(kāi)始HttpURLConnection的底層實(shí)現(xiàn)采用的是okHttp。
  • Retrofit也是square公司的锋玲, 速度快景用、傳輸層默認(rèn)使用okhttp涵叮、如果程序中集成了okhttp惭蹂、Retrofit默認(rèn)會(huì)使用OKHttp處理其他網(wǎng)絡(luò)層請(qǐng)求。Retrofit官網(wǎng)地址

這篇文章主要講okhttp的基礎(chǔ)使用

官網(wǎng)okhttp找到最新版本割粮,gradle中引入依賴

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

okhttp內(nèi)部依賴okio,所以在okio-github地址找到最新版本

compile 'com.squareup.okio:okio:1.13.0'

最后記得加入網(wǎng)絡(luò)權(quán)限

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


大綱

  • GET請(qǐng)求

  • POST請(qǐng)求

    • RequestBody--json數(shù)據(jù)提交

    • FormBody--表單數(shù)據(jù)提交

    • MultipartBody--文件上傳


一盾碗、Get請(qǐng)求

一個(gè)最簡(jiǎn)單的使用okhttp進(jìn)行網(wǎng)絡(luò)請(qǐng)求的例子,get獲取訪問(wèn)網(wǎng)頁(yè)的內(nèi)容舀瓢,返回的即是這個(gè)網(wǎng)頁(yè)的html廷雅,將內(nèi)容顯示出來(lái)

//主要代碼
    private void sendGetRuquestWithOkHttp() {
        //創(chuàng)建okHttpClient對(duì)象
        OkHttpClient okHttpClient=new OkHttpClient();
        //創(chuàng)建request,首先要有一個(gè)url
        Request request=new Request.Builder().url(netUrl).build();
        //通過(guò)request的對(duì)象去構(gòu)造得到一個(gè)Call對(duì)象,
        // 類似于將你的請(qǐng)求封裝成了任務(wù)京髓,既然是任務(wù)航缀,就會(huì)有execute()和cancel()等方法。
        Call call=okHttpClient.newCall(request);
        //以異步的方式去執(zhí)行請(qǐng)求,調(diào)用的是call.enqueue堰怨,將call加入調(diào)度隊(duì)列芥玉,
        // 然后等待任務(wù)執(zhí)行完成,我們?cè)贑allback中即可得到結(jié)果备图。
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //請(qǐng)求失敗的處理
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //請(qǐng)求成功返回結(jié)果
                //如果希望返回的是字符串
                 final String responseData=response.body().string();
                //如果希望返回的是二進(jìn)制字節(jié)數(shù)組
                byte[] responseBytes=response.body().bytes();
                //如果希望返回的是inputStream,有inputStream我們就可以通過(guò)IO的方式寫文件.
                InputStream responseStream=response.body().byteStream();
                //注意灿巧,此時(shí)的線程不是ui線程,
                // 如果此時(shí)我們要用返回的數(shù)據(jù)進(jìn)行ui更新揽涮,操作控件抠藕,就要使用相關(guān)方法
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 更新UI的操作
                            textView.setText(responseData);
                    }
                });

            }
        });
        //上面用到的enqueue是異步的方式,當(dāng)然也可以同步蒋困,
        //同步--Call有一個(gè)execute()方法盾似,你也可以直接調(diào)用call.execute()通過(guò)返回一個(gè)Response。
/*    try {
    Response response = call.execute();
    if(response.isSuccessful()){
    //同步方式下得到返回結(jié)果
    String responseByExecute=response.body().string();
    }
     } catch (IOException e) {
          e.printStackTrace();
      }*/
    }

在上面的代碼中:sendRuquestWithOkHttp()方法為網(wǎng)絡(luò)請(qǐng)求的主要代碼

  • 創(chuàng)建okHttpClient對(duì)象
  • 創(chuàng)建Request對(duì)象
  • 把請(qǐng)求封裝成任務(wù)雪标,得到Call對(duì)象
  • 以同步或異步的方法去執(zhí)行請(qǐng)求零院,將call加入調(diào)度隊(duì)列购岗,任務(wù)執(zhí)行完成,在CallBack中得到回調(diào)(異步)门粪。同步通過(guò)call.execute().body().string();得到返回結(jié)果

關(guān)于同步和異步

  • 同步調(diào)用喊积,在發(fā)起一個(gè)函數(shù)或方法調(diào)用時(shí),沒(méi)有得到結(jié)果之前玄妈,該調(diào)用就不返回乾吻,直到返回結(jié)果;同步就是發(fā)出一個(gè)請(qǐng)求后什么事都不做拟蜻,一直等待請(qǐng)求返回后才會(huì)繼續(xù)做事绎签;
  • 異步調(diào)用的概念和同步相對(duì),在一個(gè)異步調(diào)用發(fā)起后酝锅,被調(diào)用者立即返回給調(diào)用者诡必,但調(diào)用者不能立刻得到結(jié)果,被調(diào)用者在實(shí)際處理這個(gè)調(diào)用的請(qǐng)求完成后搔扁,通過(guò)狀態(tài)爸舒、通知或回調(diào)等方式來(lái)通知調(diào)用者請(qǐng)求處理的結(jié)果。異步就是發(fā)出請(qǐng)求后繼續(xù)去做其他事稿蹲,這個(gè)請(qǐng)求處理完成后會(huì)通知你扭勉,這時(shí)候就可以處理這個(gè)回應(yīng)了

用一個(gè)例子來(lái)形容:

  • 在同步環(huán)境下,客戶端叫服務(wù)端去吃飯苛聘,服務(wù)端沒(méi)聽(tīng)見(jiàn)或是沒(méi)有回答客戶端涂炎,客戶端就一直叫,直到服務(wù)端說(shuō)聽(tīng)到了设哗,它們才一起去吃飯唱捣。
  • 在異步環(huán)境下,客戶端叫服務(wù)端去吃飯网梢,客戶端也不等服務(wù)端震缭,自己就先去吃了,因?yàn)榭蛻舳艘埠苊ε焖冢凶约旱氖虑橹颍荒芤恢钡戎兑膊蛔觯?wù)端知道了之后活烙,可能馬上就去吃飯徐裸,也可能忙完手頭的事情才去吃飯。

二啸盏、POST請(qǐng)求

post和get的不同在于對(duì)Request請(qǐng)求的構(gòu)造不同(因?yàn)閜ost需要攜帶參數(shù))重贺,post方式中的Request需要傳遞一個(gè)RequestBody作為post的參數(shù)。RequestBody有兩個(gè)子類:FormBody和MultipartBody

  • RequestBody--json數(shù)據(jù)提交

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();
    f (response.isSuccessful()) {
        return response.body().string();
    } else {
        throw new IOException("Unexpected code " + response);
    }
}
  • FromBody---表單提交 這種能滿足大部分的需求

FromBody用于提交表單鍵值對(duì),key-value,其作用類似于HTML中的<form>標(biāo)記。比如username="LHX",age="21"等類似的鍵值對(duì)

我們可以使用HashMap<String气笙,String>這樣的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)接口所需參數(shù)的鍵值對(duì)次企,它的查找速度為O(1),很快,但是對(duì)于API接口參數(shù)來(lái)說(shuō)潜圃,數(shù)據(jù)不會(huì)太多缸棵,查找快體現(xiàn)不出優(yōu)勢(shì)來(lái),并且HashMap比較耗費(fèi)內(nèi)存谭期。以下是使用hashmap的例子:

private void fetchDataByPost() {
     //把參數(shù)傳進(jìn)Map中
        HashMap<String,String> paramsMap=new HashMap<>();
        paramsMap.put("name","哈哈");
        paramsMap.put("client","Android");
        paramsMap.put("id","3243598");
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : paramsMap.keySet()) {
            //追加表單信息
            builder.add(key, paramsMap.get(key));
        }
   OkHttpClient okHttpClient=new OkHttpClient();
        RequestBody formBody=builder.build();
      Request request=new   Request.Builder().url(netUrl).post(formBody).build();
        Call call=okHttpClient.newCall(request);
       call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //請(qǐng)求失敗的處理
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {  
            }
        });

}

所以我們還有一種方式可以裝取鍵值對(duì)堵第,通過(guò)ArrayList<RequestParameter>這樣的數(shù)據(jù)結(jié)構(gòu)。

//首先要有一個(gè)RequestParameter類
public class RequestParameter implements Serializable {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    private  String name;
    private  String value;
    public RequestParameter(String name,String value){
        this.name=name;
        this.value=value;
    }
}
        List<RequestParameter> parameter=new ArrayList<>();
        RequestParameter rp1=new RequestParameter("name","哈哈");
        parameter.add(rp1);
        RequestParameter rp2=new RequestParameter("client","Android");
        parameter.add(rp2);

        //創(chuàng)建一個(gè)FormBody.Builder
        FormBody.Builder builder=new FormBody.Builder();
        if (parameter!=null&&parameter.size()>0){
            for (final RequestParameter p : parameter) {
                builder.add(p.getName(),p.getValue());
            }
        }
        RequestBody formBody=builder.build();
   OkHttpClient okHttpClient=new OkHttpClient();
        Request request=new   Request.Builder().url(netUrl).post(formBody).build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //請(qǐng)求失敗的處理
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {  
            }
        });

  • MultipartBody---文件上傳

MultipartBody可以構(gòu)建與HTML文件上傳格式兼容的復(fù)雜請(qǐng)求體隧出。

   File file=new File(Environment.getExternalStorageDirectory(), "balabala.png");
        MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
        RequestBody filebody = MultipartBody.create(MEDIA_TYPE_PNG, file);
        MultipartBody.Builder multiBuilder=new MultipartBody.Builder();
        //這里是 封裝上傳圖片參數(shù)
        multiBuilder.addFormDataPart("file", file.getName(), filebody);
        //參數(shù)以添加header方式將參數(shù)封裝踏志,否則上傳參數(shù)為空
        // 設(shè)置請(qǐng)求體
        multiBuilder.setType(MultipartBody.FORM);
//這里是 封裝上傳圖片參數(shù)
        multiBuilder.addFormDataPart("file", file.getName(), filebody);
        // 封裝請(qǐng)求參數(shù),這里最重要
        HashMap<String, String> params = new HashMap<>();
        params.put("client","Android");
        params.put("uid","1061");
        params.put("token","1911173227afe098143caf4d315a436d");
        params.put("uuid","A000005566DA77");
        //參數(shù)以添加header方式將參數(shù)封裝,否則上傳參數(shù)為空
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                multiBuilder.addPart(
                        Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""),
                        RequestBody.create(null, params.get(key)));
            }
        }
 RequestBody multiBody=multiBuilder.build();
   OkHttpClient okHttpClient=new OkHttpClient();
        Request request=new   Request.Builder().url(netUrl).post(multiBody).build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //請(qǐng)求失敗的處理
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {  
            }
        });

圖片下載胀瞪,文件下載

圖片下載是通過(guò)回調(diào)的Response拿到byte[]然后decode成圖片针余;
文件下載,就是拿到inputStream做寫文件操作凄诞;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末圆雁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子幔摸,更是在濱河造成了極大的恐慌摸柄,老刑警劉巖颤练,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件既忆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嗦玖,警方通過(guò)查閱死者的電腦和手機(jī)患雇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宇挫,“玉大人苛吱,你說(shuō)我怎么就攤上這事∑鞅瘢” “怎么了翠储?”我有些...
    開(kāi)封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)橡疼。 經(jīng)常有香客問(wèn)我援所,道長(zhǎng),這世上最難降的妖魔是什么欣除? 我笑而不...
    開(kāi)封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任住拭,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滔岳。我一直安慰自己杠娱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布谱煤。 她就那樣靜靜地躺著摊求,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刘离。 梳的紋絲不亂的頭發(fā)上睹簇,一...
    開(kāi)封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音寥闪,去河邊找鬼太惠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疲憋,可吹牛的內(nèi)容都是我干的凿渊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缚柳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼埃脏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起秋忙,我...
    開(kāi)封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彩掐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后灰追,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堵幽,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年弹澎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朴下。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苦蒿,死狀恐怖殴胧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情佩迟,我是刑警寧澤团滥,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站报强,受9級(jí)特大地震影響灸姊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜躺涝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一厨钻、第九天 我趴在偏房一處隱蔽的房頂上張望扼雏。 院中可真熱鬧,春花似錦夯膀、人聲如沸诗充。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蝴蜓。三九已至,卻和暖如春俺猿,著一層夾襖步出監(jiān)牢的瞬間茎匠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工押袍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诵冒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓谊惭,卻偏偏與公主長(zhǎng)得像汽馋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子圈盔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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