1. 程式人生 > >OkHttpUtils | okhttp-OkGo的使用,完美支援RxJava

OkHttpUtils | okhttp-OkGo的使用,完美支援RxJava

image

OkGo - OkHttpUtils-2.0.0 升級後改名 OkGo,全新完美支援RxJava

該庫是封裝了okhttp的網路框架,可以與RxJava完美結合,比Retrofit更簡單易用。支援大檔案上傳下載,上傳進度回撥,下載進度回撥,表單上傳(多檔案和多引數一起上傳),鏈式呼叫,可以自定義返回物件,支援Https和自簽名證書,支援cookie自動管理,支援四種快取模式快取網路資料,支援301、302重定向,擴充套件了統一的上傳管理和下載管理功能

該專案參考了以下專案:

在此特別感謝上述作者,喜歡原作的可以去使用原專案。同時歡迎大家下載體驗本專案,如果使用過程中遇到什麼問題,歡迎反饋。

聯絡方式

  • QQ群: 489873144 (建議使用QQ群,郵箱使用較少,可能看的不及時)
  • 本群旨在為使用我的github專案的人提供方便,如果遇到問題歡迎在群裡提問。個人能力也有限,希望一起學習一起進步。

演示

imageimageimageimageimageimage

1.用法

  • 為了方便大家使用,更加通俗的理解http的網路協議,建議做網路請求的時候,對每個請求抓包後檢視請求資訊和響應資訊。
  • 如果是 Windows 作業系統,可以使用 Fiddler 對手機的請求進行抓包檢視。
  • 如果是 Mac OS 作業系統,可以使用 Charles 對手機的請求進行抓包檢視。
  • 具體的下載地址和抓包配置方法,我這就不提供了,請自行百度或谷歌。

對於Eclipse不能執行專案的,提供了apk供直接執行

本專案Demo的網路請求是我自己的伺服器,有時候可能不穩定,網速比較慢時請耐心等待。。

以下是最新版本的版本號,如果你想使用以前的版本,請點選這裡,歷史版本

  • 對於Android Studio的使用者,可以選擇新增:
    compile 'com.lzy.net:okgo:2.0.0'        //可以單獨使用,不需要依賴下方的擴充套件包
    compile 'com.lzy.net:okrx:0.1.0'        //RxJava擴充套件支援,根據需要新增
    compile 'com.lzy.net:okserver:1.1.0'    //下載管理和上傳管理擴充套件,根據需要新增
或者 compile 'com.lzy.net:okgo:+' //版本號使用 + 可以自動引用最新版 compile 'com.lzy.net:okrx:+' //版本號使用 + 可以自動引用最新版 compile 'com.lzy.net:okserver:+' //版本號使用 + 可以自動引用最新版
  • 對於Eclipse的使用者,可以選擇新增 /jar 目錄下的:
    okgo-2.0.0.jar
    okrx-0.1.0.jar
    okserver-1.1.0.jar
  • 如果是以jar包的形式引入okserver,需要在清單檔案中額外註冊一個服務
    <service android:name="com.lzy.okserver.download.DownloadService"/>
  • 如果只是用了okgo的jar,沒有使用okserver的jar,那麼不需要註冊上面的服務

其中的圖片選擇是我的另一個開源專案,完全仿微信的圖片選擇庫,自帶 矩形圖片裁剪 和 圓形圖片裁剪 功能,有需要的可以去下載使用,附上地址:https://github.com/jeasonlzy/ImagePicker

其中的九宮格控制元件也是我的開源專案,類似QQ空間,微信朋友圈,微博主頁等,展示圖片的九宮格控制元件,自動根據圖片的數量確定圖片大小和控制元件大小,使用Adapter模式設定圖片,對外提供介面回撥,使用介面載入圖片,支援任意的圖片載入框架,如 Glide,ImageLoader,Fresco,xUtils3,Picasso 等,支援點選圖片全屏預覽大圖。附上地址:https://github.com/jeasonlzy/NineGridView

2.使用注意事項

  • okgo使用的okhttp的版本是最新的 3.4.1 版本,和以前的 2.x 的版本可能會存在衝突。
  • okrx是基於RxJavaRxAndroid的擴充套件,如果不需要可以不必引入
  • okserver是對okgo的擴充套件,統一了下載管理和上傳管理,對專案有需要做統一下載的可以考慮使用該擴充套件,不需要的可以直接使用okgo即可。
  • 對於快取模式使用,需要與返回物件相關的所有javaBean必須實現Serializable介面,否者會報NotSerializableException
  • 使用快取時,如果不指定cacheKey,預設是用url帶引數的全路徑名為cacheKey
  • 使用該網路框架時,必須要在 Application 中做初始化 OkGo.init(this);

3.OkGo 目前支援

  • 一般的 get,post,put,delete,head,options請求
  • 基於Post的大文字資料上傳
  • 多檔案和多引數統一的表單上傳
  • 支援一個key上傳一個檔案,也可以一個Key上傳多個檔案
  • 大檔案下載和下載進度回撥
  • 大檔案上傳和上傳進度回撥
  • 支援cookie的記憶體儲存和持久化儲存,支援傳遞自定義cookie
  • 支援304快取協議,擴充套件四種本地快取模式,並且支援快取時間控制
  • 支援301、302重定向
  • 支援鏈式呼叫
  • 支援可信證書和自簽名證書的https的訪問,支援雙向認證
  • 支援根據Tag取消請求
  • 支援自定義泛型Callback,自動根據泛型返回物件

4.OkRx 擴充套件功能

  • 完美結合RxJava
  • 比Retrofit更簡單方便
  • 網路請求和RxJava呼叫,一條鏈點到底
  • 支援Json資料的自動解析轉換
  • OkGo包含的所有請求功能,OkRx全部支援

5.OkServer 擴充套件功能

5.1 統一的檔案下載管理(DownloadManager):

  • 結合OkGo的request進行網路請求,支援與OkGo保持相同的全域性公共引數,同時支援請求傳遞引數
  • 支援斷點下載,支援突然斷網,強殺程序後,斷點依然有效
  • 支援 下載 暫停 等待 停止 出錯 完成 六種下載狀態
  • 所有下載任務按照taskKey區分,切記不同的任務必須使用不一樣的key,否者斷點會發生覆蓋
  • 相同的下載url地址如果使用不一樣的taskKey,也會認為是兩個下載任務
  • 默認同時下載數量為3個,預設下載路徑/storage/emulated/0/download,下載路徑和下載數量都可以在程式碼中配置
  • 下載檔名可以自己定義,也可以不傳,框架自動解析響應頭或者url地址獲得檔名,如果都沒獲取到,使用default作為檔名
  • 下載管理使用了服務提高執行緒優先順序,避免後臺下載時被系統回收

5.2 統一的檔案上傳管理(UploadManager)

  • 結合OkGo的request進行網路請求,支援與OkGo保持相同的全域性公共引數,同時支援請求傳遞引數
  • 上傳只能使用PostPutDeleteOptions 這四種請求,不支援GetHead
  • 該上傳管理為簡單管理,不支援斷點續傳或分片上傳,只是簡單的將所有上傳任務使用執行緒池進行了統一管理
  • 默認同時上傳數量為1個,該數列可以在程式碼中配置修改

一、全域性配置

一般在 Aplication,或者基類中,只需要呼叫一次即可,可以配置除錯開關,全域性的超時時間,公共的請求頭和請求引數等資訊

    @Override
    public void onCreate() {
        super.onCreate();

        //---------這裡給出的是示例程式碼,告訴你可以這麼傳,實際使用的時候,根據需要傳,不需要就不傳-------------//
        HttpHeaders headers = new HttpHeaders();
        headers.put("commonHeaderKey1", "commonHeaderValue1");    //header不支援中文
        headers.put("commonHeaderKey2", "commonHeaderValue2");
        HttpParams params = new HttpParams();
        params.put("commonParamsKey1", "commonParamsValue1");     //param支援中文,直接傳,不要自己編碼
        params.put("commonParamsKey2", "這裡支援中文引數");
        //-----------------------------------------------------------------------------------//

        //必須呼叫初始化
        OkGo.init(this);

        //以下設定的所有引數是全域性引數,同樣的引數可以在請求的時候再設定一遍,那麼對於該請求來講,請求中的引數會覆蓋全域性引數
        //好處是全域性引數統一,特定請求可以特別定製引數
        try {
            //以下都不是必須的,根據需要自行選擇,一般來說只需要 debug,快取相關,cookie相關的 就可以了
            OkGo.getInstance()

                    //開啟該除錯開關,控制檯會使用 紅色error 級別列印log,並不是錯誤,是為了顯眼,不需要就不要加入該行
                    .debug("OkGo")

                    //如果使用預設的 60秒,以下三行也不需要傳
                    .setConnectTimeout(OkGo.DEFAULT_MILLISECONDS)  //全域性的連線超時時間
                    .setReadTimeOut(OkGo.DEFAULT_MILLISECONDS)     //全域性的讀取超時時間
                    .setWriteTimeOut(OkGo.DEFAULT_MILLISECONDS)    //全域性的寫入超時時間

                    //可以全域性統一設定快取模式,預設是不使用快取,可以不傳,具體其他模式看 github 介紹 https://github.com/jeasonlzy/
                    .setCacheMode(CacheMode.NO_CACHE)

                    //可以全域性統一設定快取時間,預設永不過期,具體使用方法看 github 介紹
                    .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)

                    //如果不想讓框架管理cookie,以下不需要
//                .setCookieStore(new MemoryCookieStore())                //cookie使用記憶體快取(app退出後,cookie消失)
                    .setCookieStore(new PersistentCookieStore())          //cookie持久化儲存,如果cookie不過期,則一直有效

                    //可以設定https的證書,以下幾種方案根據需要自己設定,不需要不用設定
//                    .setCertificates()                                  //方法一:信任所有證書
//                    .setCertificates(getAssets().open("srca.cer"))      //方法二:也可以自己設定https證書
//                    .setCertificates(getAssets().open("aaaa.bks"), "123456", getAssets().open("srca.cer"))//方法三:傳入bks證書,密碼,和cer證書,支援雙向加密

                    //可以新增全域性攔截器,不會用的千萬不要傳,錯誤寫法直接導致任何回撥不執行
//                .addInterceptor(new Interceptor() {
//                    @Override
//                    public Response intercept(Chain chain) throws IOException {
//                        return chain.proceed(chain.request());
//                    }
//                })

                    //這兩行同上,不需要就不要傳
                    .addCommonHeaders(headers)                                         //設定全域性公共頭
                    .addCommonParams(params);                                          //設定全域性公共引數
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

二、普通請求

0.寫在開始的話,callback回撥預設只需要複寫onSuccess,並不代表所有的回撥都只走這一個,實際開發中,錯誤回撥並沒有成功回撥使用頻繁,所以callback的失敗回撥onError並沒有宣告為抽象的,如果有需要,請自行復寫,不要再問我為什麼回撥沒有執行啊,既然onSuccess沒有執行,那麼一定是出錯了回調了onError

callback一共有以下 10 個回撥,除onSuccess必須實現以外,其餘均可以按需實現,每個方法引數詳細說明,請看下面第6點:

  • convertSuccess():解析網路返回的資料回撥
  • parseError():解析網路失敗的資料回撥
  • onBefore():網路請求真正執行前回調
  • onSuccess():網路請求成功的回撥
  • onCacheSuccess():快取讀取成功的回撥
  • onError():網路請求失敗的回撥
  • onCacheError():網路快取讀取失敗的回撥
  • onAfter():網路請求結束的回撥,無論成功失敗一定會執行
  • upProgress():上傳進度的回撥
  • downloadProgress():下載進度的回撥

Callback回撥具有如下順序,雖然順序寫的很複雜,但是理解後,是很簡單,並且合情合理的

1).無快取模式 CacheMode.NO_CACHE

網路請求成功 onBefore -> convertSuccess -> onSuccess -> onAfter
網路請求失敗 onBefore -> parseError -> onError -> onAfter

2).預設快取模式,遵循304頭 CacheMode.DEFAULT

網路請求成功,服務端返回非304 onBefore -> convertSuccess -> onSuccess -> onAfter
網路請求成功服務端返回304 onBefore -> onCacheSuccess -> onAfter
網路請求失敗 onBefore -> parseError -> onError -> onAfter

3).請求網路失敗後讀取快取 CacheMode.REQUEST_FAILED_READ_CACHE

網路請求成功,不讀取快取 onBefore -> convertSuccess -> onSuccess -> onAfter
網路請求失敗,讀取快取成功 onBefore -> parseError -> onError -> onCacheSuccess -> onAfter
網路請求失敗,讀取快取失敗 onBefore -> parseError -> onError -> onCacheError -> onAfter

4).如果快取不存在才請求網路,否則使用快取 CacheMode.IF_NONE_CACHE_REQUEST

已經有快取,不請求網路 onBefore -> onCacheSuccess -> onAfter
沒有快取請求網路成功 onBefore -> onCacheError -> convertSuccess -> onSuccess -> onAfter
沒有快取請求網路失敗 onBefore -> onCacheError -> parseError -> onError -> onAfter

5).先使用快取,不管是否存在,仍然請求網路 CacheMode.FIRST_CACHE_THEN_REQUEST

無快取時,網路請求成功 onBefore -> onCacheError -> convertSuccess -> onSuccess -> onAfter
無快取時,網路請求失敗 onBefore -> onCacheError -> parseError -> onError -> onAfter
有快取時,網路請求成功 onBefore -> onCacheSuccess -> convertSuccess -> onSuccess -> onAfter
有快取時,網路請求失敗 onBefore -> onCacheSuccess -> parseError -> onError -> onAfter

1.基本的網路請求

OkGo.get(Urls.URL_METHOD)     // 請求方式和請求url
    .tag(this)                       // 請求的 tag, 主要用於取消對應的請求
    .cacheKey("cacheKey")            // 設定當前請求的快取key,建議每個不同功能的請求設定一個
    .cacheMode(CacheMode.DEFAULT)    // 快取模式,詳細請看快取介紹
    .execute(new StringCallback() {
        @Override
        public void onSuccess(String s, Call call, Response response) {
            // s 即為所需要的結果
        }
    });

2.請求 Bitmap 物件

OkGo.get(Urls.URL_IMAGE)//
    .tag(this)//
    .execute(new BitmapCallback() {
        @Override
        public void onSuccess(Bitmap bitmap, Call call, Response response) {
            // bitmap 即為返回的圖片資料
        }
    });

3.請求 檔案下載

OkGo.get(Urls.URL_DOWNLOAD)//
    .tag(this)//
    .execute(new FileCallback("file.jpg") {  //檔案下載時,需要指定下載的檔案目錄和檔名
        @Override
        public void onSuccess(File file, Call call, Response response) {
            // file 即為檔案資料,檔案儲存在指定目錄
        }

        @Override
        public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
            //這裡回撥下載進度(該回調在主執行緒,可以直接更新ui)
        }
    });

4.普通Post,直接上傳String型別的文字

一般此種用法用於與伺服器約定的資料格式,當使用該方法時,params中的引數設定是無效的,所有引數均需要通過需要上傳的文字中指定,此外,額外指定的header引數仍然保持有效。

OkGo.post(Urls.URL_TEXT_UPLOAD)//
    .tag(this)//
    .upString("這是要上傳的長文字資料!")//
    .execute(new StringCallback() {
        @Override
        public void onSuccess(String s, Call call, Response response) {
            //上傳成功
        }

        @Override
        public void upProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
            //這裡回撥上傳進度(該回調在主執行緒,可以直接更新ui)
        }
    });

5.普通Post,直接上傳Json型別的文字

該方法與postString沒有本質區別,只是資料格式是json,一般來說,需要自己建立一個實體bean或者一個map,把需要的引數設定進去,然後通過三方的Gson或者fastjson轉換成json字串,最後直接使用該方法提交到伺服器。

HashMap<String, String> params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "這裡是需要提交的json格式資料");
params.put("key3", "也可以使用三方工具將物件轉成json字串");
params.put("key4", "其實你怎麼高興怎麼寫都行");
JSONObject jsonObject = new JSONObject(params);

OkGo.post(Urls.URL_TEXT_UPLOAD)//
    .tag(this)//
    .upJson(jsonObject.toString())//
    .execute(new StringCallback() {
        @Override
        public void onSuccess(String s, Call call, Response response) {
            //上傳成功
        }


        @Override
        public void upProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
            //這裡回撥上傳進度(該回調在主執行緒,可以直接更新ui)
        }
    });

6.https請求(證書可以在全域性初始化的時候設定,不用每次請求設定一遍)

OkGo.get("https://kyfw.12306.cn/otn")//
        .tag(this)//
        .headers("Connection", "close")           //如果對於部分自簽名的https訪問不成功,需要加上該控制頭
        .headers("header1", "headerValue1")//
        .params("param1", "paramValue1")//
//      .setCertificates()                             //方法一:信任所有證書
//      .setCertificates(getAssets().open("srca.cer")) //方法二:也可以設定https證書
        //方法三:傳入bks證書,密碼,和cer證書,支援雙向加密
//      .setCertificates(getAssets().open("aaaa.bks"), "123456", getAssets().open("srca.cer"))
        .execute(new HttpsCallBack(this));

7.請求功能的所有配置講解

以下程式碼包含了以下內容:

  • 一次普通請求所有能配置的引數,真實使用時不需要配置這麼多,按自己的需要選擇性的使用即可
  • params新增引數的時候,最後一個isReplace為可選引數,預設為true,即代表相同key的時候,後新增的會覆蓋先前新增的
  • 多檔案和多引數的表單上傳,同時支援進度監聽
  • 自簽名網站https的訪問,呼叫setCertificates方法即可
  • 為單個請求設定超時,比如涉及到檔案的需要設定讀寫等待時間多一點。
  • Cookie一般情況下只需要在初始化的時候呼叫setCookieStore即可實現cookie的自動管理,如果特殊業務需要,需要手動額外向伺服器傳遞自定義的cookie,可以在每次請求的時候呼叫addCookie方法,該方法提供了3個過載形式,可以根據自己的需要選擇使用。
OkGo.get(Urls.URL_METHOD) // 請求方式和請求url, get請求不需要拼接引數,支援get,post,put,delete,head,options請求
    .tag(this)               // 請求的 tag, 主要用於取消對應的請求
    .connTimeOut(10000)      // 設定當前請求的連線超時時間
    .readTimeOut(10000)      // 設定當前請求的讀取超時時間
    .writeTimeOut(10000)     // 設定當前請求的寫入超時時間
    .cacheKey("cacheKey")    // 設定當前請求的快取key,建議每個不同功能的請求設定一個
    .cacheTime(5000)         // 快取的過期時間,單位毫秒
    .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST) // 快取模式,詳細請看第四部分,快取介紹
    .setCertificates(getAssets().open("srca.cer")) // 自簽名https的證書,可變引數,可以設定多個
    .addInterceptor(interceptor)            // 新增自定義攔截器
    .headers("header1", "headerValue1")     // 新增請求頭引數
    .headers("header2", "headerValue2")     // 支援多請求頭引數同時新增
    .params("param1", "paramValue1")        // 新增請求引數
    .params("param2", "paramValue2")        // 支援多請求引數同時新增
    .params("file1", new File("filepath1")) // 可以新增檔案上傳
    .params("file2", new File("filepath2")) // 支援多檔案同時新增上傳
    .addUrlParams("key", List<String> values) //這裡支援一個key傳多個引數
    .addFileParams("key", List<File> files) //這裡支援一個key傳多個檔案
    .addFileWrapperParams("key", List<HttpParams.FileWrapper> fileWrappers)//這裡支援一個key傳多個檔案
    .addCookie("aaa", "bbb")    // 這裡可以傳遞自己想傳的Cookie
    .addCookie(cookie)          // 可以自己構建cookie
    .addCookies(cookies)        // 可以一次傳遞批量的cookie
     //這裡給出的泛型為 ServerModel,同時傳遞一個泛型的 class物件,即可自動將資料結果轉成物件返回
    .execute(new DialogCallback<ServerModel>(this) {
        @Override
        public void onBefore(BaseRequest request) {
            // UI執行緒 請求網路之前呼叫
            // 可以顯示對話方塊,新增/修改/移除 請求引數
        }

        @Override
        public ServerModel convertSuccess(Response response) throws Exception{
            // 子執行緒,可以做耗時操作
            // 根據傳遞進來的 response 物件,把資料解析成需要的 ServerModel 型別並返回
            // 可以根據自己的需要,丟擲異常,在onError中處理
            return null;
        }

        @Override
        public void parseError(Call call, IOException e) {
            // 子執行緒,可以做耗時操作
            // 用於網路錯誤時在子執行緒中執行資料耗時操作,子類可以根據自己的需要重寫此方法
        }

        @Override
        public void onSuccess(ServerModel serverModel, Call call, Response response) {
            // UI 執行緒,請求成功後回撥
            // ServerModel 返回泛型約定的實體型別引數
            // call        本次網路的請求資訊,如果需要檢視請求頭或請求引數可以從此物件獲取
            // response    本次網路訪問的結果物件,包含了響應頭,響應碼等        
        }

        @Override
        public void onCacheSuccess(ServerModel serverModel, Call call) {
            // UI 執行緒,快取讀取成功後回撥
            // serverModel 返回泛型約定的實體型別引數
            // call        本次網路的請求資訊
        }

        @Override
        public void onError(Call call, Response response, Exception e) {
            // UI 執行緒,請求失敗後回撥
            // call        本次網路的請求物件,可以根據該物件拿到 request
            // response    本次網路訪問的結果物件,包含了響應頭,響應碼等            
            // e           本次網路訪問的異常資訊,如果伺服器內部發生了錯誤,響應碼為 404,或大於等於500
        }