1. 程式人生 > >OkHttpUtils-2.0.0 升級後改名 OkGo,全新完美支援 RxJava,比 Retrofit 更簡單易用。

OkHttpUtils-2.0.0 升級後改名 OkGo,全新完美支援 RxJava,比 Retrofit 更簡單易用。

該專案參考了以下專案:

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

聯絡方式

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

演示

imageimageimageimageimageimage

文件目錄(點選快速導航)

1.用法

請抓包看網路資料,log 有些資料不列印,不會抓包請百度,學一次受用終生,重要的事情說三遍

請抓包看網路資料,log 有些資料不列印,不會抓包請百度,學一次受用終生,重要的事情說三遍

請抓包看網路資料,log 有些資料不列印,不會抓包請百度,學一次受用終生,重要的事情說三遍

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

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

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

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

  • 對於 Android Studio 的使用者,可以選擇新增:
compile 'com.lzy.net:okgo:2.1.4'        //可以單獨使用,不需要依賴下方的擴充套件包
compile 'com.lzy.net:okrx:0.1.2'        //RxJava 擴充套件支援,根據需要新增
compile 'com.lzy.net:okserver:1.1.3'    //下載管理和上傳管理擴充套件,根據需要新增

或者

compile 'com.lzy.net:okgo:+'        //版本號使用 + 可以自動引用最新版
compile 'com.lzy.net:okrx:+'        //版本號使用 + 可以自動引用最新版
compile 'com.lzy.net:okserver:+'    //版本號使用 + 可以自動引用最新版
  • 對於 Eclipse 的使用者,可以選擇新增 /jar 目錄下的: ```java okhttp-3.4.1.jar //okhttp 官方包 (必須導) okio-1.9.0.jar //okio 官方包(必須導) okgo-2.1.4.jar //okgo 基本功能包(必須導)

okrx-0.1.2.jar //okrx 擴充套件支援包,想用 rxjava 呼叫的必須要導(同時還需要 rxjava 的 jar,自行下載,不提供) okserver-1.1.3.jar //okserver 擴充套件支援包,使用下載管理必須要

 * 如果是以 jar 包的形式引入`okserver`,需要在清單檔案中額外註冊一個服務
```java
<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 擴充套件功能

該功能並沒有在文件中寫出,詳細使用方法請自行看 demo 中的程式碼,有詳細的註釋,不在文件中贅述。

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,或者基類中,只需要呼叫一次即可,可以配置除錯開關,全域性的超時時間,公共的請求頭和請求引數等資訊

不要忘記了在清單檔案中註冊 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()

                // 開啟該除錯開關,列印級別 INFO,並不是異常,是為了顯眼,不需要就不要加入該行
                // 最後的 true 表示是否列印 okgo 的內部異常,一般開啟方便除錯錯誤
                .debug("OkGo", Level.INFO, true)

                //如果使用預設的 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)

                //可以全域性統一設定超時重連次數,預設為三次,那麼最差的情況會請求 4 次(一次原始請求,三次重連請求),不需要可以設定為 0
                .setRetryCount(3)

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

                //可以設定 https 的證書,以下幾種方案根據需要自己設定
                .setCertificates()                                  //方法一:信任所有證書,不安全有風險
//              .setCertificates(new SafeTrustManager())            //方法二:自定義信任規則,校驗服務端證書
//              .setCertificates(getAssets().open("srca.cer"))      //方法三:使用預埋證書,校驗服務端證書(自簽名證書)
//              //方法四:使用 bks 證書和密碼管理客戶端證書(雙向認證),使用預埋證書,校驗服務端證書(自簽名證書)
//               .setCertificates(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"))//

                //配置 https 的域名匹配規則,詳細看 demo 的初始化介紹,不需要就不要加入,使用不當會導致 https 握手失敗
//               .setHostnameVerifier(new SafeHostnameVerifier())

                //可以新增全域性攔截器,不需要就不要加入,錯誤寫法直接導致任何回撥不執行
//                .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.請求 檔案下載

FileCallback具有三個過載的構造方法,分別是

FileCallback():空參構造
FileCallback(String destFileName):可以額外指定檔案下載完成後的檔名
FileCallback(String destFileDir, String destFileName):可以額外指定檔案的下載目錄和下載完成後的檔名

檔案目錄如果不指定,預設下載的目錄為 sdcard/download/,檔名如果不指定,則按照以下規則命名:

1.首先檢查使用者是否傳入了檔名,如果傳入,將以使用者傳入的檔名命名
2.如果沒有傳入,那麼將會檢查服務端返回的響應頭是否含有Content-Disposition=attachment;filename=FileName.txt該種形式的響應頭,如果有,則按照該響應頭中指定的檔名命名檔案,如FileName.txt
3.如果上述響應頭不存在,則檢查下載的檔案 url,例如:http://image.baidu.com/abc.jpg,那麼將會自動以abc.jpg命名檔案
4.如果 url 也把檔名解析不出來,那麼最終將以nofilename命名檔案

OkGo.get(Urls.URL_DOWNLOAD)//
    .tag(this)//
    .execute(new FileCallback() {  //檔案下載時,可以指定下載的檔案目錄和檔名
        @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 引數仍然保持有效。

預設會攜帶以下請求頭

Content-Type: text/plain;charset=utf-8

如果你對請求頭有自己的要求,可以使用這個過載的形式,傳入自定義的content-type

upString("這是要上傳的長文字資料!", MediaType.parse("application/xml")) // 比如上傳 xml 資料,這裡就可以自己指定請求頭

OkGo.post(Urls.URL_TEXT_UPLOAD)//
    .tag(this)//
//    .params("param1", "paramValue1")//  這裡不要使用 params,upString 與 params 是互斥的,只有 upString 的���據會被上傳
    .upString("這是要上傳的長文字資料!")//
//    .upString("這是要上傳的長文字資料!", MediaType.parse("application/xml")) // 比如上傳 xml 資料,這裡就可以自己指定請求頭
    .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 字串,最後直接使用該方法提交到伺服器。

預設會攜帶以下請求頭,請不要手動修改,okgo 也不支援自己修改

Content-Type: application/json;charset=utf-8

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)//
//    .params("param1", "paramValue1")//  這裡不要使用 params,upJson 與 params 是互斥的,只有 upJson 的資料會被上傳
    .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.上傳圖片或者檔案

上傳檔案支援檔案與引數一起同時上傳,也支援一個 key 上傳多個檔案,以下方式可以任選

特別要注意的是

1).很多人會說需要在上傳檔案到時候,要把Content-Type修改掉,變成multipart/form-data,就像下面這樣的。其實在使用 OkGo 的時候,只要你添加了檔案,這裡的的Content-Type不需要你手動設定,OkGo 自動新增該請求頭,同時,OkGo 也不允許你修改該請求頭。

Content-Type: multipart/form-data; boundary=f6b76bad-0345-4337-b7d8-b362cb1f9949

2).如果沒有檔案,那麼 OkGo 將自動使用以下請求頭,同樣 OkGo 也不允許你修改該請求頭。

Content-Type: application/x-www-form-urlencoded

3).如果你的伺服器希望你在沒有檔案的時候依然使用multipart/form-data請求,那麼可以使用.isMultipart(true)這個方法強制修改,一般來說是不需要強制的。

OkGo.post(URL_FORM_UPLOAD)//
    .tag(this)//
    .isMultipart(true)       // 強制使用 multipart/form-data 表單上傳(只是演示,不需要的話不要設定。預設就是 false)
    .params("param1", "paramValue1")         // 這裡可以上傳引數
    .params("file1", new File("filepath1"))   // 可以新增檔案上傳
    .params("file2", new File("filepath2"))     // 支援多檔案同時新增上傳
    .addFileParams("key", List<File> files)    // 這裡支援一個 key 傳多個檔案
    .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)
        }
    });

7.https 請求,需要在初始化的時候配置以下程式碼

OkGo.getInstance()
    ...
    //可以設定 https 的證書,以下幾種方案根據需要自己設定
       .setCertificates()                                  //方法一:信任所有證書,不安全有風險
    // .setCertificates(new SafeTrustManager())            //方法二:自定義信任規則,校驗服務端證書
    // .setCertificates(getAssets().open("srca.cer"))      //方法三:使用預埋證書,校驗服務端證書(自簽名證書)
    //方法四:使用 bks 證書和密碼管理客戶端證書(雙向認證),使用預埋證書,校驗服務端證書(自簽名證書)
    // .setCertificates(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"))//

    //配置 https 的域名匹配規則,詳細看 demo 的初始化介紹,不需要就不要加入,使用不當會導致 https 握手失敗
    // .setHostnameVerifier(new SafeHostnameVerifier())
    ...

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

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

  • 一次普通請求所有能配置的引數,真實使用時不需要配置這麼多,按自己的需要選擇性的使用即可
  • params新增引數的時候,最後一個isReplace為可選引數,預設為true,即代表相同key的時候,後新增的會覆蓋先前新增的
  • 多檔案和多引數的表單上傳,同時支援進度監聽
  • 為單個請求設定超時,比如涉及到檔案的需要設定讀寫等待時間多一點。
OkGo.post(Urls.URL_METHOD)    // 請求方式和請求 url, get 請求不需要拼接引數,支援 get,post,put,delete,head,options 請求
    .tag(this)               // 請求的 tag, 主要用於取消對應的請求
    .isMultipart(true)       // 強制使用 multipart/form-data 表單上傳(只是演示,不需要的話不要設定。預設就是 false)
    .connTimeOut(10000)      // 設定當前請求的連線超時時間
    .readTimeOut(10000)      // 設定當前請求的讀取超時時間
    .writeTimeOut(10000)     // 設定當前請求的寫入超時時間
    .cacheKey("cacheKey")    // 設定當前請求的快取 key,建議每個不同功能的請求設定一個
    .cacheTime(5000)         // 快取的過期時間,單位毫秒
    .cacheMode(CacheMode.FIRST_CACHE_THEN_REQUEST) // 快取模式,詳細請看第四部分,快取介紹
    .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 傳多個檔案
    //這裡給出的泛型為 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
        }

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

        @Override
        public void onAfter(ServerModel serverModel, Exception e) {
            // UI 執行緒,請求結束後回撥,無論網路請求成功還是失敗,都會呼叫,可以用於關閉顯示對話方塊
            // ServerModel 返回泛型約定的實體型別引數,如果網路請求失敗,該物件為 null
            // e           本次網路訪問的異常資訊,如果伺服器內部發生了錯誤,響應碼為 404,或大於等於 500
        }

        @Override
        public void upProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
            // UI 執行緒,檔案上傳過程中回撥,只有請求方式包含請求體才回調(GET,HEAD 不會回撥)
            // currentSize  當前上傳的大小(單位位元組)
            // totalSize   需要上傳的總大小(單位位元組)
            // progress     當前上傳的進度,範圍 0.0f ~ 1.0f
            // networkSpeed 當前上傳的網速(單位秒)
        }

        @Override
        public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
            // UI 執行緒,檔案下載過程中回撥
            //引數含義同 上傳相同
        }
    });

9.取消請求

每個請求前都設定了一個引數tag,取消則通過OkGo.cancel(tag)執行。 例如:在 Activity 中,當 Activity 銷燬取消請求,可以在 onDestory 裡面統一取消。

@Override
protected void onDestroy() {
    super.onDestroy();

    //根據 Tag 取消請求
    OkGo.getInstance().cancelTag(this);

    //取消所有請求
    OkGo.getInstance().cancelAll();
}

10.同步的請求

execute 方法不傳入 callback 即為同步的請求,返回Response物件,需要自己解析

Response response = OkGo.get("http://www.baidu.com")//
                                .tag(this)//
                                .headers("aaa", "111")//
                                .params("bbb", "222")
                                .execute();

11.引數的順序

新增 header 和 param 的方法各有三個地方,在提交的時候,他們是有順序的,如果對提交順序有需要的話,請注意這裡

  • 第一個地方,全域性初始化時,使用OkGo.getInstance().addCommonHeaders(),OkGo.getInstance().addCommonParams() 新增
HttpHeaders headers = new HttpHeaders();
headers.put("HKAAA", "HVAAA");
headers.put("HKBBB", "HVBBB");
HttpParams params = new HttpParams();
params.put("PKAAA", "PVAAA"); 
params.put("PKBBB", "PVBBB");

OkGo.getInstance()
    .addCommonHeaders(headers) //設定全域性公共頭
    .addCommonParams(params);  //設定全域性公共引數
  • 第二個地方,callbackonBefore方法中新增
public abstract class CommonCallback<T> extends AbsCallback<T> {
    @Override
    public void onBefore(BaseRequest request) {
        super.onBefore(request);

        request.headers("HKCCC", "HVCCC")//
                .headers("HKDDD", "HVDDD")//
                .params("PKCCC", "PVCCC")//
                .params("PKDDD", "PVDDD")//
    }
}
  • 第三個地方,執行網路請求的時候新增
OkGo.get(Urls.URL_METHOD)//
        .tag(this)//
        .headers("HKEEE", "HVEEE")//
        .headers("HKFFF", "HVFFF")//
        .params("PKEEE", "PVEEE")//
        .params("PKFFF", "PVFFF")//
        .execute(new MethodCallBack<>(this, ServerModel.class));

那麼,最終執行請求的引數的新增順序為

  • Header 順序: HKAAA -> HKBBB -> HKEEE -> HKFFF -> HKCCC -> HKDDD
  • Params 順序: PKAAA -> PKBBB -> PKEEE -> PKFFF -> PKCCC -> PKDDD

總結一句話就是,全域性新增的在最開始,callback 新增的在最後,請求新增的在中間

三、自定義 CallBack 使用

目前內部提供的包含AbsCallbackStringCallBack ,BitmapCallback ,FileCallBack ,可以根據自己的需求去自定義 Callback

  • AbsCallback: 所有回撥的父類,抽象類
  • StringCallBack:如果返回值型別是純文字資料,即可使用該回調
  • BitmapCallback:如果請求的是圖片資料,則可以使用該回調
  • FileCallBack:如果要做檔案下載,則必須使用該回調,內部封裝了關於檔案下載進度回撥的方法

該網路框架的核心使用方法即為Callback的繼承使用,詳細請看 Demo 原始碼中callback包下的程式碼。

因為不同的專案需求,可能對資料格式進行了不同的封裝,於是在 Demo 中的進行了詳細的程式碼示例,以下是詳細介紹:

  • JsonCallback:繼承自AbsCallback,一般來說,伺服器返回的響應碼都包含 code,msg,data 三部分,在此根據自己的業務需要完成相應的邏輯判斷,並對資料進行解析,可以使用 Gson 或者 fastjson,將解析的物件返回。
  • DialogCallback:繼承自JsonCallback,對需要在網路請求的時候顯示對話方塊,使用該回調。
  • StringDialogCallback:繼承自EncryptCallback,如果網路返回的資料只是純文字,使用該回調
  • BitmapDialogCallback :繼承自BitmapCallback,如果網路返回的是 Bitmap 物件,使用該回調
  • DownloadFileCallBack :繼承自FileCallback,如果需要做檔案下載,使用該回調

以上基本是包含了大部分的業務邏輯,具體情況請參照 demo 示例,根據業務需求修改!

四、快取的使用

使用快取前,必須讓快取的資料javaBean物件實現Serializable介面,否者會報NotSerializableException

因為快取的原理是將物件序列化後直接寫入 資料庫中,如果不實現Serializable介面,會導致物件無法序列化,進而無法寫入到資料庫中,也就達不到快取的效果。

對於DEFAULT快取模式,超時時間是無效的,因為該模式是完全遵循標準的 http 協議的,快取時間是依靠服務端響應頭來控制,所以客戶端的 cacheTime 引數無效

目前提供了五種CacheMode快取模式,每種快取模式都可以指定對應的CacheTime,不同的模式會有不同的方法回撥順序,詳細請看上面第二部分的 callback 執行順序