OkHttp 3 基本用法

OkHttp 也已經出來很久了,相信大家也都在項目中使用了,今天來對 OkHttp 使用進行一個簡單的總結


一、概述


HTTP 是超文本傳輸協議,也是互聯網上應用最爲廣泛的一種網絡協議,高效的進行 HTTP 使用可以使你的東西更快的加載並節省帶寬


OkHttp 是 HTTP 客戶端的有效應用,OkHttp 處理了很多疑難雜症:

  • 例如會從很多常用連接問題中自動恢復
  • 如果你的服務器設置了多個 IP 地址,當第一個IP連接失敗的時候,OkHttp 會自動嘗試下一個 IP
  • OkHttp 還處理了代理服務器問題和 SSL 握手失敗問題
  • 支持 HTTP/2,HTTP/2 通過使用多路複用技術在一個單獨的 TCP 連接上支持併發,通過在一個連接上一次性發送多個請求來發送或接受數據
  • 如果 HTTP/2 不可用,連接池複用技術也可以極大地減少延遲

      使用 OkHttp 無需重寫您程序中的網絡代碼,OkHttp 實現了幾乎和 HttpURLConnection 一樣的 API,OkHttp 支持 Android2.3 及以上

官網地址:http://square.github.io/okhttp/

GitHub 地址:https://github.com/square/okhttp


二、使用教程詳解


首先使用前我們需要在 app 目錄級別下的 build.gradle 中添加:

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


1. 異步 GET  請求


進行網絡數據加載,想必第一個我們就得先來說 GET 請求,這裏我們如果是新建的項目別忘了添加網絡權限

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

    /**
     * 異步Get請求
     * @param view
     */
    public void getRequest(View view) {
        //創建 OkHttpClient 對象
        OkHttpClient okHttpClient = new OkHttpClient();
        //創建 Request
        Request request = new Request.Builder()
                .url("https://www.baidu.com/")
                .build();

        Call call = okHttpClient.newCall(request);
        //發送請求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "失敗------" + e.getLocalizedMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e(TAG, "成功------" + response);
                String result = response.body().string();
                Log.e(TAG, result);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

      以上我們就完成了一個異步 Get 請求,首先創建了 Okhttp 對象,並構造了 Request 對象,並傳入了一個 url,主意這裏Request.Builder 還可以設置如 header、method 等的參數方法,然後通過 request 的對象去構造得到一個 Call 對象,最後我們調用Call 對象的 enqueue() 來執行,注意這裏也可以選擇同步 execute() 請求,將 call 加入到調度隊列,然後等待執行完成,在 Callback 中得到回調結果,這裏我們需要注意的就是,onResponse 回調的參數是 reponse,一般來說,如果我們希望獲得返回的是字符串,可以通過 response.body().string() 獲取,如果希望獲得返回的二進制節數組,則通過 response.body().bytes() 等


2. 異步POST請求


    /**
     * 異步Post請求
     *
     * @param view
     */
    public void postRequest(View view) {
        //創建 OkHttpClient 對象
        OkHttpClient okHttpClient = new OkHttpClient();
        //構建 RequestBody
        RequestBody formBody = new FormBody.Builder()
                .add("鍵", "值")
                .build();
        //構建 Request
        Request request = new Request.Builder()
                .url("https://www.baidu.com/")
                .post(formBody)
                .build();

        Call call = okHttpClient.newCall(request);
        //發送請求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "失敗------" + e.getLocalizedMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                Log.e(TAG, "成功------" + response);
                String result = response.body().string();
                Log.e(TAG, result);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

      這裏需要注意一下 OkHttp3 異步 POST 請求和 OkHttp2.x 有一點區別就是沒有 FormEncodingBuilder 這個類,替代它的就是FormBody,大家都知道,post 的時候,參數是包含在請求體中的,所以我們通過 FormBody 來添加多個 String 鍵值對,然後去構造 RequestBody,來完成我們 Request 的構造,後面的步驟基本就和 get 請求一樣了,還有就是這了提交的表單格式可以有多種

如果表單是 json:

        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, "你的json");

如果數據包含文件:

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
                .build();

接下來我們將會講具體解到


3. 異步上傳文件


定義上傳文件得類型:

    //上傳文件的類型
    public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");


    /**
     * 異步上傳文件
     *
     * @param view
     */
    public void postFile(View view) {
        OkHttpClient okHttpClient = new OkHttpClient();
        File file = new File("上傳的文件");
        Request request = new Request.Builder()
                .url("上傳的地址")
                .post(RequestBody.create(MEDIA_TYPE_MARKDOWN,file))
                .build();

        Call call = okHttpClient.newCall(request);
        
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }

這裏也要注意不要忘記添加權限:

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

可以看到上傳文件其實也是一個 POST 請求


4. 異步上傳 Multipart 文件


    //定義類型
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

    /**
     * 異步上傳Multipart文件
     */
    public void sendMultipart() {
        OkHttpClient okHttpClient = new OkHttpClient();

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("title", "nihao")
                .addFormDataPart("image", "image.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/image.jpg")))
                .build();

        Request request = new Request.Builder()
                .header("Authorization", "Client-ID " + "...")
                .url("https://api.imgur.com/3/image")
                .post(requestBody)
                .build();

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

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

異步上傳文件這種場景在開發中還是很常用的,上傳不同類型的文件同時還需要傳其他類型的字段,這些用 OkHttp3 實現起來很簡單,這裏我們只是做了一個示例,實際開發中大家還要具體對應自己的服務器聯調


5. 異步下載文件 


    /**
     * 異步下載文件
     *
     * @param view
     */
    public void downFile(View view) {
        OkHttpClient okHttpClient = new OkHttpClient();

        Request request = new Request.Builder().url("下載地址").build();

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) {
                InputStream inputStream = response.body().byteStream();
                FileOutputStream fileOutputStream = null;
                try {
                    fileOutputStream = new FileOutputStream(new File("/sdcard/iamge.jpg"));
                    byte[] buffer = new byte[2048];
                    int len = 0;
                    while ((len = inputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, len);
                    }
                    fileOutputStream.flush();
                } catch (IOException e) {
                    Log.i(TAG, "IOException");
                    e.printStackTrace();
                }

                Log.d(TAG, "文件下載成功");
            }
        });
    }


6. 設置超時時間和緩存


 	File sdcache = getExternalCacheDir();
        int cacheSize = 10 * 1024 * 1024;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        OkHttpClient okHttpClient=builder.build();

       這裏需要注意得是和 OkHttp2.x 不同的是,不能通過 OkHttpClient 直接設置超時和緩存了,而是通過 OkHttpClient.Builder 來設置,通過 builder 配置好 OkHttpClient 後用 builder.builder() 來返回 OkHttpClient


       我們用到的大概也就這些了,都是一些比較基本的用法,在實際項目中,大家肯定還得進行進一步的封裝,要不這樣使用大家也看到了,怪累,今天就寫到這裏,有錯誤的地方請指出


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章