Okhttp的基本使用

前言

okhttp無疑Android端最火熱的網(wǎng)絡(luò)請求框架了,由Square公司貢獻(xiàn)。
下面對以O(shè)KHttp3來介紹OKHttp的使用方法。
本人菜雞水平,寫此文章為了加深印象,如果發(fā)現(xiàn)錯誤或不足懇請指正。謝謝

異步和同步的區(qū)別

同步請求:發(fā)送方發(fā)出數(shù)據(jù)后,等接收方發(fā)回響應(yīng)以后才發(fā)下一個數(shù)據(jù)包的通訊方式。
異步請求:發(fā)送方發(fā)出數(shù)據(jù)后,不等接收方發(fā)回響應(yīng),接著發(fā)送下個數(shù)據(jù)包的通訊方式


來張圖

添加依賴

 implementation 'com.squareup.okhttp3:okhttp:4.2.1'
 implementation 'com.squareup.okio:okio:2.2.2'

okio依賴必須有不然會報錯

get請求

我們先看一下異步請求

      //獲取client
        OkHttpClient client=new OkHttpClient.Builder().build();
        //構(gòu)建request,這里不寫方法的話默認(rèn)為get()
        Request request=new Request.Builder()
                .url("http://www.baidu.com")
                .build(); //最后一定要build一下
        //構(gòu)建Call
        Call call=client.newCall(request);
        //異步請求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.d(TAG,"onFailure");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Log.d(TAG,response.body().string());
                Log.d(TAG,Thread.currentThread().getName());
            }
        });

我們看這個最簡單的demo
LoginActivity123: OkHttp http://www.baidu.com/...
logcat打印出來這句話,說明了回調(diào)接口的onFailure方法和onResponse執(zhí)行在子線程,如果想進(jìn)行UI操作,還需把消息發(fā)到主線程進(jìn)行

我們在看同步的請求

new Thread(new Runnable() {
            @Override
            public void run() {
                //獲取client
                OkHttpClient client=new OkHttpClient.Builder().build();
                //構(gòu)建request,這里不寫方法的話默認(rèn)為get()
                Request request=new Request.Builder()
                        .url("http://www.baidu.com")
                        .build(); //最后一定要build一下
                //構(gòu)建Call
                Call call=client.newCall(request);
                //同步請求
                try {
                    Response response = call.execute();
                    if (response.isSuccessful()){
                        Log.d(TAG,"responsecode:"+response.code());
                        Log.d(TAG,"responseMsg:"+response.message());
                        Log.d(TAG,"res:"+response.body().string());
                        //此時在子線程,更新UI需要在主線程
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

我們可以看到,前三個步驟和異步請求的方式一樣,有區(qū)別的地方就是call這個對象執(zhí)行的方法是enqueue還是execute。
需要注意的:response.body().string()方法也必須放在子線程中。當(dāng)執(zhí)行這行代碼得到結(jié)果后,再跳轉(zhuǎn)到UI線程修改UI

post請求

post請求也分同步請求和異步請求,和get請求的同步異步類似,我們在開發(fā)中,用到的大多數(shù)是異步請求,所以我們只看一下異步的請求。

//獲取client
        OkHttpClient client = new OkHttpClient.Builder()
                .build();
        //創(chuàng)建RequestBody(Form表單)
        RequestBody body = new FormBody.Builder()
                .add("username", "admin")
                .add("password", "123456")
                .build();
        //構(gòu)建建Rquest
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        //構(gòu)建Call
        final Call call = client.newCall(request);
        //發(fā)起請求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i(TAG, "onFailure");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                Log.i(TAG, "onResponse");
            }
        });

這里我們需要注意的是,當(dāng)請求方式為post請求時,我們需要把請求方式進(jìn)行設(shè)置,就是post這個方法,并且我們需要請求對象傳進(jìn)去。這里是把表單請求體對象作為post方法的參數(shù)。我們來看看這幾種:
1.使用FormBody傳遞鍵值對參數(shù)
這種方式用來上傳String類型的鍵值對
2.使用RequestBody傳遞Json

     MediaType JSON = MediaType.parse("application/json; charset=utf-8");//數(shù)據(jù)類型為json格式,
     String jsonStr = "{\"username\":\"admin\",\"password\":\"123456\"}";//json數(shù)據(jù).
     RequestBody body1 = RequestBody.create(JSON,jsonStr);

3.使用RequestBody傳遞File

    MediaType fileType = MediaType.parse("File/*");
    File file = new File("path");
    RequestBody body = RequestBody.create(fileType , file );

4.使用MultipartBody同時傳遞鍵值對和File對象

MultipartBody multipartBody =new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("groupId","123")//添加鍵值對參數(shù)
                .addFormDataPart("username","admin")
                .addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件
                .build();

以上的這幾種方法都是構(gòu)建requestBody的方法,實現(xiàn)了傳遞不能類型的對象。

文件下載

        InputStream is = null;
        FileOutputStream fos = null;
        try{
            is = response.body().byteStream();//從服務(wù)器得到輸入流對象
            long sum = 0;
            File dir = new File("path");
            if (!dir.exists()){
                dir.mkdirs();
            }
            File file = new File(dir, filename);//根據(jù)目錄和文件名得到file對象
            fos = new FileOutputStream(file);
            byte[] buf = new byte[1024*8];
            int len = 0;
            while ((len = is.read(buf)) != -1){
                fos.write(buf, 0, len);
            }
            fos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (is!=null)
                is.close();
            if (fos!=null)
                fos.close();
        }

Response中可以獲取流對象,有了流對象我們就可以自己實現(xiàn)文件的下載,在最后的finally語句塊中要把流對象close。

總結(jié)

1.response.body().string()本質(zhì)是輸入流的讀操作,這行代碼必須放在子線程。
2.response.body().string()只能調(diào)用一次,在第一次時有返回值,第二次再調(diào)用時將會返回null。
3.異步請求不需要開啟子線程,enqueue方法會自動將網(wǎng)絡(luò)請求部分放入子線程中執(zhí)行。


感謝閱讀,歡迎點贊評論!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容