Android OkHttp的基本用法

轉(zhuǎn)載:http://www.itdecent.cn/p/c478d7a20d03
OkHttp可以說是如今最為流行的網(wǎng)絡(luò)請(qǐng)求框架之一,今天來探究下OkHttp 的使用方法,包括Get 請(qǐng)求、Post 請(qǐng)求、上傳下載文件、上傳下載圖片等功能

在使用OKHttp之前,首先要先了解如下幾個(gè)比較核心的類:

  • OkHttpClient:客戶端對(duì)象
  • Request:訪問請(qǐng)求,Post請(qǐng)求中需要包含RequestBody
  • RequestBody:請(qǐng)求數(shù)據(jù),在Post請(qǐng)求中用到
  • Response:即網(wǎng)絡(luò)請(qǐng)求的響應(yīng)結(jié)果
  • MediaType:數(shù)據(jù)類型,用來表明數(shù)據(jù)是json,image,pdf等一系列格式
  • client.newCall(request).execute():同步的請(qǐng)求方法
  • client.newCall(request).enqueue(Callback callBack):異步的請(qǐng)求方法,但Callback是執(zhí)行在子線程中的,因此不能在此進(jìn)行UI更新操作

在使用前需要先在項(xiàng)目中添加OkHttp的依賴庫(kù),在對(duì)應(yīng)的Module的gradle中添加如下語句

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

此外,OkHttp內(nèi)部依賴另一個(gè)開源庫(kù)OkIo,所以也要將它導(dǎo)入進(jìn)來

compile 'com.squareup.okio:okio:1.11.0'

然后同步項(xiàng)目即可OkHttp的GitHub地址是:OkHttp
OkIo的GitHub地址是:OkIo

一、Get 請(qǐng)求

最常見的網(wǎng)絡(luò)請(qǐng)求方式可以說就是Get請(qǐng)求了,這里來獲取我在簡(jiǎn)書的個(gè)人主頁的網(wǎng)頁內(nèi)容

public void get(View view) {
        OkHttpClient client = new OkHttpClient();
        //構(gòu)造Request對(duì)象
        //采用建造者模式,鏈?zhǔn)秸{(diào)用指明進(jìn)行Get請(qǐng)求,傳入Get的請(qǐng)求地址
        Request request = new Request.Builder().get().url("http://www.itdecent.cn/u/9df45b87cfdf").build();
        Call call = client.newCall(request);
        //異步調(diào)用并設(shè)置回調(diào)函數(shù)
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(GetActivity.this, "Get 失敗");
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                final String responseStr = response.body().string();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

需要注意的是,異步調(diào)用的回調(diào)函數(shù)是在子線程當(dāng)中的,因?yàn)樾枰肏andler或者runOnUiThread來更新UI
這里使用到了一個(gè)Toast工具類,用戶判斷當(dāng)前線程是否是主線程,是的話則直接彈出Toast,否則利用runOnUiThread來彈出Toast

public class ToastUtil {

    public static void showToast(final Activity activity, final String message) {
        if ("main".equals(Thread.currentThread().getName())) {
            Log.e("ToastUtil", "在主線程");
            Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
        } else {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.e("ToastUtil", "不在主線程");
                    Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

}

此外,在回調(diào)函數(shù)的以下方法中

public void onResponse(Call call, final Response response)

如果希望獲得返回的是字符串,則可以使用

response.body().string()

如果需要的是字節(jié)數(shù)組,則使用

response.body().bytes()

如果需要的是輸入流,則使用

response.body().byteStream()

二、Post 類型

在OkHttp中用Post方法向服務(wù)器發(fā)送一個(gè)請(qǐng)求體時(shí),請(qǐng)求體需要是一個(gè)RequestBody。這個(gè)請(qǐng)求體可以是:

  • key-value:鍵值對(duì)類型
  • String:字符串類型
  • Form:類似于Html的表單數(shù)據(jù)提交
  • Stream:流類型
  • File:文件類型

三、Post 鍵值對(duì)

 public void postParameter(View view) {
        OkHttpClient client = new OkHttpClient();
        //構(gòu)建FormBody,傳入要提交的參數(shù)
        FormBody formBody = new FormBody
                .Builder()
                .add("username", "initObject")
                .add("password", "initObject")
                .build();
        final Request request = new Request.Builder()
                .url("http://www.itdecent.cn/")
                .post(formBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(PostParameterActivity.this, "Post Parameter 失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                ToastUtil.showToast(PostParameterActivity.this, "Code:" + String.valueOf(response.code()));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

這里來向簡(jiǎn)書的網(wǎng)站主頁提交兩個(gè)參數(shù)值,可以通過Post來實(shí)現(xiàn)模擬登錄的功能。當(dāng)然這里只是模擬了Post操作而已,提交參數(shù)后會(huì)跳轉(zhuǎn)到404頁面

public void onResponse(Call call, Response response)

方法中通過

response.code()

可以得到整數(shù)類型的結(jié)果碼:404

四、Post 字符串

在上面的例子中Post傳遞的是參數(shù)對(duì),有時(shí)候我們會(huì)有要傳送字符串的需要,比如向服務(wù)器發(fā)送一個(gè)JSON字符串。那么就可以用如下方法:

public void postString(View view) {
        OkHttpClient client = new OkHttpClient();
        //RequestBody中的MediaType指定為純文本,編碼方式是utf-8
        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"),
                "{username:admin;password:admin}");
        final Request request = new Request.Builder()
                .url("http://www.itdecent.cn/")
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(PostStringActivity.this, "Post String 失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                ToastUtil.showToast(PostStringActivity.this, "Code:" + String.valueOf(response.code()));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

五、Post 表單

通過查看網(wǎng)站登錄頁的Html源代碼,通常都可以查看到如下格式的登錄表單

<form id="fm1" action="" method="post">
    <input id="username" name="username" type="text"/>    
    <input id="password" name="password" type="password"/>                    
</form>

這里使用到 MuiltipartBody 來構(gòu)建一個(gè)RequestBody,這是 RequestBody 的一個(gè)子類,提交表單數(shù)據(jù)就是利用這個(gè)類來實(shí)現(xiàn)的

public void postForm(View view) {
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("username", "葉應(yīng)是葉")
                .addFormDataPart("password", "葉應(yīng)是葉")
                .build();
        final Request request = new Request.Builder()
                .url("http://www.itdecent.cn/")
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(PostFormActivity.this, "Post Form 失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                ToastUtil.showToast(PostFormActivity.this, "Code:" + String.valueOf(response.code()));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

六、Post 流

public void postStreaming(View view) {
        final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new RequestBody() {
            @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) + " × " + i;
                }
                return Integer.toString(n);
            }
        };
        Request request = new Request.Builder()
                .url("https://api.github.com/markdown/raw")
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(PostStreamingActivity.this, "Post Streaming 失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                ToastUtil.showToast(PostStreamingActivity.this, "Code:" + String.valueOf(response.code()));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

七、Post 文件

public void postFile(View view) {
        OkHttpClient client = new OkHttpClient();
        final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
        File file = new File("README.md");
        Request request = new Request.Builder()
                .url("https://api.github.com/markdown/raw")
                .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(PostFileActivity.this, "Post File 失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                ToastUtil.showToast(PostFileActivity.this, "Code:" + String.valueOf(response.code()));
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(responseStr);
                    }
                });
            }
        });
    }

八、下載圖片

public void downImage(View view) {
        OkHttpClient client = new OkHttpClient();
        final Request request = new Request
                .Builder()
                .get()
                .url("http://avatar.csdn.net/B/0/1/1_new_one_object.jpg")
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                ToastUtil.showToast(DownImageActivity.this, "下載圖片失敗");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream inputStream = response.body().byteStream();
                //將圖片顯示到ImageView中
                final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        iv_result.setImageBitmap(bitmap);
                    }
                });
                //將圖片保存到本地存儲(chǔ)卡中
                File file = new File(Environment.getExternalStorageDirectory(), "image.png");
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                byte[] temp = new byte[128];
                int length;
                while ((length = inputStream.read(temp)) != -1) {
                    fileOutputStream.write(temp, 0, length);
                }
                fileOutputStream.flush();
                fileOutputStream.close();
                inputStream.close();
            }
        });
    }

指定圖片地址并下載成功后,獲取圖片的輸入流,先用Bitmap decodeStream(InputStream is)方法將輸入流轉(zhuǎn)為Bitmap然后顯示出來,然后將圖片保存到本地存儲(chǔ)卡根目錄下
記得要申請(qǐng)存儲(chǔ)卡的寫權(quán)限

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

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評(píng)論 19 139
  • 參考Android網(wǎng)絡(luò)請(qǐng)求心路歷程Android Http接地氣網(wǎng)絡(luò)請(qǐng)求(HttpURLConnection) 一...
    合肥黑閱讀 21,722評(píng)論 7 63
  • 前言:現(xiàn)在做 Android 開發(fā),應(yīng)該絕大部分都是用 OkHttp 來做網(wǎng)絡(luò)請(qǐng)求的。可見 OkHttp 的強(qiáng)大。...
    張少林同學(xué)閱讀 3,504評(píng)論 0 14
  • 最好的生活狀態(tài)是順其自然,而且心中有愛。不管你本來的起始點(diǎn)是好還是不好,只要心中始終如一,最后總會(huì)走向你自己狀...
    簡(jiǎn)彤閱讀 174評(píng)論 0 0
  • 一、TOPK 分析工具的定義 這個(gè)學(xué)期,通過學(xué)習(xí)黃徳華老師(江湖人稱:華仔老師)主講的《創(chuàng)業(yè)搭檔》課程,我們學(xué)會(huì)了...
    一往直前閱讀 1,157評(píng)論 0 0

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