前言
之前使用okhttputil,由於鴻洋的該框架並未對於回調數據進行過度處理,callback需要自定義處理,所以在項目使用時對其進行了封裝,後來發現OkGo對於Callback進行了封裝,自己的封裝Callback和OkGo的有些相似,然後在新的項目中就使用基於OkGo二次封裝的網絡請求框架了,這裏主要介紹OkGo的基於MVC下的二次封裝和使用
本文案例的項目地址 https://github.com/caixingcun/OkGoDemo
OkGo地址 https://github.com/jeasonlzy/okhttp-OkGo/wiki
OkHttpUtil 地址 https://github.com/hongyangAndroid/okhttputils
分析
現在的網絡框架正常都是使用的json從後臺獲取數據,這裏保存RESTful風格
這裏需要首先跟後臺約定好傳遞數據的格式
常規數據格式
{
"Code":100,
"Msg":"請求成功",
"Result":{
"Name":"老王"
}
}
常規錯誤數據格式
{
"Code":101,
"Msg":"請求失敗",
}
數組數據
{
"Code":100,
"Msg":"請求成功",
"Result":[
{
"Name":"老王",
"Age":23
},
{
"Name":"老李",
"Age":25
}
]
}
數組請求爲空
{
“Code”:100,
“Msg”:”請求成功”,
“Result”:[]
}
OkGo的集成
1.添加依賴
compile ‘com.readystatesoftware.chuck:library:1.0.4’
compile ‘com.readystatesoftware.chuck:library:1.0.4’
2.App中初始化
有特定需求的可以按okgo文檔配置
OkGo.getInstance().init(this);
3.下載OkGo案例
將demo下callback中的內容複製進自己的項目
這部分是作者編寫的可供修改的框架部分
有報錯基本就是類不存,或者重寫import
把相關類複製進來
可以看一下當前複製進來的主要幾個類
Convert.java 轉換
JsonConvert.java 帶泛型轉換
JsonCallback.java 泛型轉換回調
LzyResponse.java 實體類
SimpleResponse.java
顧名思義 也可以看出這些類的大概意思
基本上Convert就是基本的Gson轉換
JsonConvert就是再上面的基礎上對於網絡請求數據進行了初步處理
這裏已經在分析返回錯誤碼
也就是我們最上面定義的{“Code”:101,”Msg”:”“}
我們來看一下作者的轉換類 LzyResponse.java
基本格式實際上是跟我們統一的
再看一下JsonCallback.java
應該是對於傳遞的泛型進行分類型處理
OkGo的修改
我這裏先使用node.js創建一個本地簡易網絡訪問服務器
創建一組json請求數據
OkGo.<String>get("http://192.168.1.79:3000/simplerequest")
.execute(new StringCallback(){
@Override
public void onSuccess(Response<String> response) {
tv.setText(response.body());
}
});
注意上面的是大寫的Code
下面添加一串跟OkGo中Lzy相同的數據結構,並請求
代碼
OkGo.<SimpleResponse>get("http://192.168.1.79:3000/okgoget")
.execute(new JsonCallback<SimpleResponse>() {
@Override
public void onSuccess(Response<SimpleResponse> response) {
tv.setText(response.body().msg);
}
});
整改開始,就是將作者所給框架的code msg修改爲跟我們後臺約定一樣的格式
改了LzyResponse和SimpleResponse,JsonConvert就可以了,很快
再來通過作者的二次框架來訪問大寫Code Msg
基本上能用了
但是要知道爲什麼自己要進行二次封裝網絡框架
正常的StringCallback也可以進行網絡請求,就是因爲方便
這裏需要使用LzyResponse
然後對於JsonConvert和JsonCallback進行整改
當我們使用LzyRespose接收數據時,會發現我們拿不到我們的數據,在Callback回調中
數據
{"Code":104,"Msg":"授權無效"}
代碼
OkGo.<LzyResponse<Object>>get("http://192.168.1.79:3000/okgo104")
.execute(new JsonCallback<LzyResponse<Object>>(){
@Override
public void onSuccess(Response<LzyResponse<Object>> response) {
tv.setText(response.body().Msg+response.body().Code);
}
});
在訪問後臺總會發生各種問題,尤其時身份問題
還有各種錯誤,這些東西需要統一處理
看下JsonConvert的源碼
int code = lzyResponse.Code;
//這裏的0是以下意思
//一般來說服務器會和客戶端約定一個數表示成功,其餘的表示失敗,這裏根據實際情況修改
if (code == 0) {
//noinspection unchecked
return (T) lzyResponse;
} else if (code == 104) {
throw new IllegalStateException("用戶授權信息無效");
} else if (code == 105) {
throw new IllegalStateException("用戶收取信息已過期");
} else {
//直接將服務端的錯誤信息拋出,onError中可以獲取
throw new IllegalStateException("錯誤代碼:" + code + ",錯誤信息:" + lzyResponse.Msg);
}
我們在這裏只需要將和後臺約定的Code狀況都添加進來
也可以像我之前的代碼
拋出自定義異常 然後統一到onError中處理
int code = responseBean.Code;
String msg = responseBean.Msg;
//這裏的0是以下意思
//一般來說服務器會和客戶端約定一個數表示成功,其餘的表示失敗,這裏根據實際情況修改
//這裏的異常會拋到 JsonCallback中 的onError
if (code == 0 || code == 103) {
//noinspection unchecked
return (T) responseBean;
} else {
throw new MyException("{\"Code\":"+code+",\"Msg\":\""+msg+"\"}");
}
在JsonCallback中重寫onError進行異常處理
需要注意onError回調中response.code()是網絡請求的code
不是我們數據中的code
if (code == 100) {
return (T) lzyResponse;
} else {
throw new MyException("{\"Code\":"+code+",\"Msg\":\""+msg+"\"}");
}
MyException
public class MyException extends IllegalStateException {
private LzyResponse errorBean;
public MyException(String s) {
super(s);
errorBean = new Gson().fromJson(s, LzyResponse.class);
}
public LzyResponse getErrorBean() {
return errorBean;
}
}
JsonCallback中 onError
@Override
public void onError(com.lzy.okgo.model.Response<T> response) {
super.onError(response);
int code = response.code();
if (code == 404) {
Log.d("JsonCallback", "404 當前鏈接不存在");
}
if (response.getException() instanceof SocketTimeoutException) {
Log.d("JsonCallback", "請求超時");
} else if (response.getException() instanceof SocketException) {
Log.d("JsonCallback", "服務器異常");
} else if (response.getException() instanceof MyException) {
switch (((MyException) response.getException()).getErrorBean().Code) {
case 107: //約定的身份表示過期
//重登錄
break;
}
}
}
對於回調封裝到這裏就結束了
外部調用簡單封裝
public class OkGoUtil {
public static <T> void getRequets(String url, Object tag, Map<String, String> map, JsonCallback<T> callback) {
// TODO: 2017/10/13 加密 時間戳等 請求日誌打印
Log.d("OkGoUtil", "method get");
OkGo.<T>get(url)
.tag(tag)
.params(map)
.execute(callback);
}
public static <T> void postRequest(String url, Object tag, Map<String, String> map, JsonCallback<T> callback) {
// TODO: 2017/10/13 加密 時間戳等 請求日誌打印
Log.d("OkGoUtil", "method post");
OkGo.<T>post(url)
.tag(tag)
.params(map)
.execute(callback);
}
}
最後
來看一下調用情況
接口
http://localhost:3000/api/post
數據
{"Code":100,
"Msg":"請求成功",
"Result":{"name":"老王","hobby":"愛吃雞"}
}
新建數據bean
public class SimpleBean {
/**
* name : 老王
* habby : 吃雞
*/
private String name;
private String habby;
}
get set方法這裏不貼
請求
OkGoUtil.getRequets("http://192.168.1.79:3000/okgo_get", this, new HashMap<String, String>(), new JsonCallback<LzyResponse<SimpleBean>>() {
@Override
public void onSuccess(Response<LzyResponse<SimpleBean>> response) {
tv.setText(response.body().Result.getName() + "-" + response.body().Result.getHabby());
}
});
最終結果
好了封裝完畢
之後每次使用 只需要將Result中數據bean創建出來
其他所有異常 在與後臺約定好後通過Code 在JsonCallback中的onError中進行處理即可
在onSuccess中只處理 Code = 100的正常情況
如果有需要在主線程需要做什麼特殊處理
在調用時的Callback中重寫onError也是可以拿到具體的錯誤數據的