Android 網(wǎng)絡框架_目前(2016年11月7日)最流行的網(wǎng)絡框架OKHttp3

現(xiàn)在每篇文章前都會吐槽下自己的生活事情,也當作個記錄,本來想寫這篇博客很久的了,看標題就知道,想 11 月 7 日就開始寫的了,可是現(xiàn)在(2016年11月27日22:45:12)還沒寫完,因為這段事件趕公司的即時聊天的項目,還有每個星期都會來一篇算法的文章或做算法的題,因此導致這篇文章很久還沒寫完,不想拖下去,趕緊寫完。


一、 OKHttp基礎(chǔ)

我們可以通過右鍵 new——》Module——》java Library 的方式來創(chuàng)建一個 Module 的方式來測試一下 OKHttp3 ,為什么是創(chuàng)建 java Library 呢?因為對于一般的網(wǎng)絡框架而已,我們只需要創(chuàng)建 java Library就可以了,不必要創(chuàng)建 Android Library 。

然后導入我們的OKHttp3,具體的官網(wǎng)在之前的系列文章中就有個介紹:
CSDN:http://blog.csdn.net/Two_Water/article/details/53055524
簡書:http://www.itdecent.cn/p/049a91e9958a

創(chuàng)建lib

1.同步請求和異步請求

創(chuàng)建完項目后,來了解一下OKHttp3的同步請求和異步請求,雖然官網(wǎng)就有很詳細的例子,可是最好還是自己讀嘗試一次,就算是跟著官網(wǎng)的例子敲一遍,還是有一番體會的。


package com.liangdianshui.http.lib;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * OKHttp 同步請求和異步請求
 *
 * Created by liangdianshui on 2016/11/8
 */
public class SendRequest {

    /**
     * 同步請求
     * <p>
     * 會阻塞當前線程
     * </p>
     *
     * @param url
     */
    public static void sendRequest(String url) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 異步請求
     *
     * @param url
     */
    public static void sendAsyncRequest(String url) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    System.out.println(Thread.currentThread().getId());
                }
            }
        });
    }

    public static void main(String args[]) {
        sendRequest("http://blog.csdn.net/two_water");
        System.out.println("-------------------------------------------");
        System.out.println(Thread.currentThread().getId());
        sendAsyncRequest("http://blog.csdn.net/two_water");

    }
}


2.請求頭和響應頭

在上一個博客中也有介紹到響應頭和請求頭,也介紹了一大堆參數(shù),那么我們?nèi)绾问褂眠@些參數(shù)呢?


package com.liangdianshui.http.lib;

import java.io.IOException;

import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 增加請求頭的請求
 * Created by liangdianshui on 2016/11/8
 */
public class AddHeaderRequest {

    public static void addHeaderRequest(String url) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .addHeader("User-Agent", "liangdianshui")
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                Headers requestHeaders = request.headers();
                System.out.println("----------Request Headers------------");
                for (int i = 0; i < requestHeaders.size(); i++) {
                    System.out.println(requestHeaders.name(i) + " : " + requestHeaders.value(i));
                }

                Headers responseHeaders = response.headers();
                System.out.println("------------Response Headers-----------");
                for (int i = 0; i < responseHeaders.size(); i++) {
                    System.out.println(responseHeaders.name(i) + " : " + responseHeaders.value(i));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String args[]) {
        addHeaderRequest("http://blog.csdn.net/two_water");
    }
}

我們也可以通過 Fiddler 來查看到我們請求中的請求頭的,合理使用這些工具可以驗證我們獲取的數(shù)據(jù)是否正確,少走一些彎路

Fiddler查看請求頭和響應頭

3.添加請求參數(shù)的get請求

請求參數(shù)的 get 請求,我們使用和風網(wǎng)的免費天氣查詢 api 作為例子,和風網(wǎng)的官網(wǎng)地址:

http://www.heweather.com/

我們首先的注冊一個用戶,就會分配key:

和風網(wǎng)免費注冊后的個人認證key

注冊完成后我們就可以去查找相關(guān)的API文檔,看看如何調(diào)用:

和風網(wǎng)天氣api接口

最后就是上代碼了:


package com.liangdianshui.http.lib;

import java.io.IOException;

import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 添加請求參數(shù)的get請求
 * <p>
 * Created by Administrator on 2016/11/16 0016.
 */
public class AddQueryParameterRequest {

    /**
     * 使用和風網(wǎng)的免費天氣查詢的api
     */
    public static void addQueryParameterRequest() {
        OkHttpClient client=new OkHttpClient();
        HttpUrl httpUrl=HttpUrl.parse("https://free-api.heweather.com/v5/now")
                .newBuilder()
                .addQueryParameter("city","shenzhen")
                .addQueryParameter("key"," 9b82700caecd4d3aa709c54a7593754d")
                .build();
        Request request=new Request.Builder().url(httpUrl.toString()).build();
        try {
            Response response=client.newCall(request).execute();
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        addQueryParameterRequest();
    }

}


4.post請求
如果使用公共的 api 提交 post 請求,相對于 get 請求來說,是相對麻煩一些的,因此我們自己寫一個簡單的服務,來請求 post 請求,

服務器的代碼主要是這個:


post請求服務器代碼

客戶端代碼:


package com.liangdianshui.http.lib;

import java.io.IOException;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by liangdianshui on 2016/11/27 0027.
 */
public class PostRequest {

    public static void postRequest(String url, String name, String password) {
        OkHttpClient client = new OkHttpClient();
        FormBody body = new FormBody.Builder().add("username", name).add("password", password).build();
        Request request = new Request.Builder().url(url).post(body).build();

        try {
            Response reponse = client.newCall(request).execute();
            if (reponse.isSuccessful()) {
                System.out.println(reponse.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        postRequest("http://localhost:8080/OKHttpTest/OKHttpPost", "liangdianshui", "123456");
    }
}

運行的結(jié)果:

post請求結(jié)果

在這里呢,我們先了解一個知識點:

POST

可以看到 post 請求中默認的類型就是:application/x-www-form-urlencoded 因此我們可以查看下我們 OKHttp 中的 FormBody 中的源碼:

OKHttp源碼中FormBody的post請求

可以看到我們使用的 FormBody 就是這個類型的,而 multipart/form-data 這個類型主要是用于上傳文件等相關(guān)操作的。因為這個上傳方式不做編碼處理,你上傳什么就是什么


5.上傳文件

這里我們先寫一下服務器的代碼,也要了解一下到底 http 是怎樣上傳文件的

先寫一個 html 的頁面:

上傳文件的頁面

然后我們看下服務器的代碼,寫的非常的簡單,主要是我們只是了解下上傳文件的流程而已。

上傳文件post請求服務器代碼

我們來看下效果:

post請求上傳文件

好了,服務器完成了,我們來查看一下上傳文件的協(xié)議是怎樣的:

查看協(xié)議

可以看到,如果我們自己寫上傳文件的代碼還是比較復雜的,只不過這里面的過程,OKHttp 都幫我們封裝好了,因此使用起來還是比較簡單的。


package com.liangdianshui.http.lib;

import java.io.File;
import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by liangdianshui on 2016/11/28 0028.
 */
public class MultiparHttp {

    public static void main(String args[]) {
        //上傳一張本地的圖片
        RequestBody imageBody = RequestBody.create(MediaType.parse("image/jpeg"), new File("C:\\Users\\Administrator\\Desktop\\service\\liangdianshui.jpg"));
        MultipartBody body = new MultipartBody.Builder().
                setType(MultipartBody.FORM).  //要配置上傳的類型,否則會上傳不成功
                addFormDataPart("name", "nate").
                addFormDataPart("filename", "girl.jpg", imageBody).build();
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().
                url("http://localhost:8080/OKHttpTest/UploadServlet").post(body).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                System.out.println(response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

運行的結(jié)果:


上傳圖片

6. Http 緩存

其實 OkHttp 給我們封裝好了 Http 的緩存,用起來還是挺方便的,可是我們不能僅限于在用,先不說我們要創(chuàng)造屬于自己的藝術(shù)品,起碼我們得知其所以然,只有這樣,才能有利于我們技術(shù)的進階。竟然說到 Http 的緩存,那么我們必需得問,為什么要有 Http 請求緩存呢?每個設計肯定有它的思想所在,我們得理解,得探討。

為什么要有 Http 請求的緩存?
(1): 緩存緩解了網(wǎng)絡瓶頸的問題,不需要更多的網(wǎng)絡帶寬就能更快的加載頁面。
(2):緩存減少了冗余的數(shù)據(jù)傳輸,節(jié)省了網(wǎng)絡費用。
(3):緩存降低了對原始服務器的要求,服務器可以更快的響應。同時,搜索引擎的爬蟲機器人也能根據(jù)過期機制降低爬取的頻率,也能有效降低服務器的壓力。

當然 Http 請求緩存給我們帶來了一系列的好處之外,也有它的不足,那么它有什么不足或缺點呢?
(1)占空間:緩存沒有清理機制,這些緩存的文件會永久性地保存在機器上,在特定的時間內(nèi),這些文件可能是幫了你大忙,但是時間一長,我們已經(jīng)不再需要瀏覽之前的這些網(wǎng)頁,這些文件就成了無效或者無用的文件,它們存儲在用戶硬盤中只會占用空間而沒有任何用處,如果要緩存的東西非常多,那就會撐暴整個硬盤空間。
(2)不即現(xiàn):因為緩存,有時候我們明明修改了樣式文件、圖片、視頻或腳本,刷新頁面或部署到站點之后看不到修改之后的效果。所以在產(chǎn)品開發(fā)的時候我們總是想辦法避免緩存產(chǎn)生,而在產(chǎn)品發(fā)布之時又在想策略管理緩存提升網(wǎng)頁的訪問速度。這就給我們帶來了一定的困擾。

那么是怎樣實現(xiàn) Http 的緩存的呢?
其實 Http 緩存在不同的類型上緩存的方式不一樣,可是原理還是一樣的,我們通過了解瀏覽器緩存來探討一下是怎樣實現(xiàn)的?

Http緩存

Http 請求緩存中相關(guān)的字段有哪些呢?

Http請求緩存緩存相關(guān)字段

最后通過請求我的博客來看一下緩存:


請求博客查看緩存

其中:
Cache-control 常見的取值有 private、no-cache、max-age、must-revalidate 等,默認為private 。其作用根據(jù)不同的重新瀏覽方式分為以下幾種情況:
(1) 打開新窗口
如果指定 cache-control 的值為 private、no-cache、must-revalidate,那么打開新窗口訪問時都會重新訪問服務器。而如果指定了 max-age 值,那么在此值內(nèi)的時間里就不會重新訪問服務器,例如:
Cache-control: max-age=5
表示當訪問此網(wǎng)頁后的5秒內(nèi)再次訪問不會去服務器
(2) 在地址欄回車
如果值為 private 或 must-revalidate(和網(wǎng)上說的不一樣),則只有第一次訪問時會訪問服務器,以后就不再訪問。如果值為 no-cache,那么每次都會訪問。如果值為 max-age ,則在過期之前不會重復訪問。
(3) 按后退按扭
如果值為 private、must-revalidate、max-age,則不會重訪問,而如果為 no-cache,則每次都重復訪問
(4) 按刷新按扭
無論為何值,都會重復訪問

最后我們來看下 OKHttp 是如何設置緩存的:


    /**
     * 請求一個網(wǎng)址,設置緩存
     * <p>要進行緩存,首先網(wǎng)址的服務器端先要支持緩存,再者,我們可以通過
     * @code:{  public Builder cacheControl(CacheControl cacheControl) } 的方式控制客戶端的緩存</p>
     *
     * @param url
     * @param file
     * @param maxCacheSize
     * @throws IOException
     */
    public static void cachRequest(String url, File file, int maxCacheSize) throws IOException {
        Cache cache = new Cache(file, maxCacheSize);
        OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        String body = response.body().string();
    }

想了解 OKHttp 是如何實現(xiàn)緩存的,我們可以先從 OKHttp 整個的流程圖中入手:

OKHttp 流程圖

本來還想寫完緩存的分析的,可是看了下時間(2016年11月29日01:25:49)已經(jīng)很晚了,還是睡了,明天還得上班,其實 OKHttp 緩存的實現(xiàn)看了很久源碼,里面一大堆的 if 判斷,看的有點暈,不過整體大概的原理還是可以理解的,細節(jié)的部分就略過了。哎,總是對自己那么仁慈,可能這就是跟大神的距離了。

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

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,836評論 25 709
  • 參考Android網(wǎng)絡請求心路歷程Android Http接地氣網(wǎng)絡請求(HttpURLConnection) 一...
    合肥黑閱讀 21,697評論 7 63
  • 1. 點擊“設置” 2. 點擊“通用” 3. 點擊“設備管理” 4. 點擊“CITIC”這一條 5. 點擊“信任”
    YAO閱讀 619評論 1 1
  • 前幾天,晚上下班,去市場買菜,然后回家。進屋后,打開音樂。默認播放的列表,有很多歌,現(xiàn)在都不喜歡聽了,但有幾個人我...
    魚小哆閱讀 2,226評論 0 12

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