OkHttpUtils | okhttp-OkGo的使用,完美支援RxJava
OkGo - OkHttpUtils-2.0.0
升級後改名 OkGo
,全新完美支援RxJava
該庫是封裝了okhttp的網路框架,可以與RxJava完美結合,比Retrofit更簡單易用。支援大檔案上傳下載,上傳進度回撥,下載進度回撥,表單上傳(多檔案和多引數一起上傳),鏈式呼叫,可以自定義返回物件,支援Https和自簽名證書,支援cookie自動管理,支援四種快取模式快取網路資料,支援301、302重定向,擴充套件了統一的上傳管理和下載管理功能
該專案參考了以下專案:
在此特別感謝上述作者,喜歡原作的可以去使用原專案。同時歡迎大家下載體驗本專案,如果使用過程中遇到什麼問題,歡迎反饋。
聯絡方式
- QQ群: 489873144 (建議使用QQ群,郵箱使用較少,可能看的不及時)
- 本群旨在為使用我的github專案的人提供方便,如果遇到問題歡迎在群裡提問。個人能力也有限,希望一起學習一起進步。
演示
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
是基於RxJava
和RxAndroid
的擴充套件,如果不需要可以不必引入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保持相同的全域性公共引數,同時支援請求傳遞引數
- 上傳只能使用
Post
,Put
,Delete
,Options
這四種請求,不支援Get
,Head
- 該上傳管理為簡單管理,不支援斷點續傳或分片上傳,只是簡單的將所有上傳任務使用執行緒池進行了統一管理
- 默認同時上傳數量為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 }