android使用gson和泛型解析伺服器回撥的封裝
android使用gson和泛型解析伺服器回撥的封裝
概述
前面我們介紹瞭如何使用Gson解析和建立json,這裡我們繼續介紹如何使用泛型來封裝伺服器回撥。
本文主要的技術點有
- 使用類的泛型和方法的泛型
- 結合gson封裝伺服器json回撥
1 建立通用的回撥Model
以這個伺服器回撥為例。
{
"server_time": 1497611816029,
"data": {
"name": "jady",
"age": 12
},
"success": true
}
這個json裡面server_time
和success
的型別是固定不變的,但是data的型別卻會經常改變,比如這裡傳回來的是User
,另一個介面傳回來的可能就是Student
了。
首先建立對應的類:
public class ServerCallbackModel<T> {
private long server_time;
private T data;
private boolean success;
private String err_code;
private String message;
public long getServer_time() {
return server_time;
}
public void setServer_time(long server_time) {
this.server_time = server_time;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2 封裝伺服器回撥
這裡我們寫的伺服器回撥是基於已經拿到伺服器回撥的json字串。
2.1 回撥的抽象基類:
public abstract class HttpCallback<T> {
public static final String TAG = "HttpCallback";
protected Type genericityType;
public HttpCallback() {
Type genericSuperclass = getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
this.genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
} else {
this.genericityType = Object.class;
}
}
public abstract void onResolve(T t);
public abstract void onFailed(String err_code, String message);
public Type getGenericityType() {
return genericityType;
}
}
這裡定義了一個構造方法,兩個抽象方法,我們先看構造方法,
Type genericSuperclass = getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
this.genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
} else {
this.genericityType = Object.class;
}
Type: Java中所有型別的公共高階介面。它們包括原始型別、引數化型別、陣列型別、型別變數和基本型別。
getGenericSuperclass()獲得帶有泛型的父類: 獲得帶有泛型的父類。
ParameterizedType: 引數化型別,即泛型。
getActualTypeArguments:獲取引數化型別的陣列,泛型引數可能有多個
getActualTypeArguments()[0]
得到了泛型的第一個引數T的型別,賦值給代表當前類泛型型別的成員變數genericityType
。如果不是引數化型別,比如在接收伺服器回撥的地方沒有加泛型型別,那麼我們就給genericityType
賦值Object的class物件。
genericityType
是用來在後面作為Gson解析的型別引數的。
再來看看抽象方法:
public abstract void onResolve(String json);
public abstract void onFailed(String err_code, String message);
聰明的你一定發現了沒有onSuccess()
,別急,看到後面你就明白了。
onResolve()
就是用來解析json的了,子類需要重寫它來具體解析。
onFailed
是錯誤回撥。
2.2 針對剛才伺服器物件封裝的抽象子類
public abstract class ServerCallback<T, V> extends HttpCallback<T>{
@Override
public void onResolve(String json) {
boolean returnJson = false;
if (genericityType instanceof Class) {
switch (((Class) genericityType).getSimpleName()) {
case "Object":
case "String":
returnJson = true;
break;
default:
break;
}
}
if (returnJson) {
onSuccess((V) json);
} else {
T t = (new Gson()).fromJson(json, genericityType);
if (t instanceof ServerCallbackModel) {
ServerCallbackModel<V> callbackData = (ServerCallbackModel) t;
V result = callbackData.getData();
if (callbackData.isSuccess()) {
this.onSuccess(result);
} else {
onFailed(callbackData.getErr_code(), callbackData.getMessage());
}
} else {
onSuccess((V) t);
}
}
}
public void onFailed(String error_code, String error_message) {
if (enableShowToast()) {
Toast.makeText(HttpManager.mContext, error_message, Toast.LENGTH_SHORT).show();
}
onFailure(error_code, error_message);
}
public abstract void onSuccess(V data);
public abstract void onFailure(String error_code, String error_message);
public boolean enableShowToast() {
return false;
}
}
首先,我們定義了一個抽象的帶兩個型別引數的泛型類,第一個引數是Gson
對映的外層物件,比如可以傳入我們剛才定義的ServerCallbackModel
,第二個引數就是外層物件中的資料了,比如ServerCallbackModel
中的data。
然後來分析下類中的方法,先來看看非抽象的方法:
public void onResolve(String json)
這個方法用來解析伺服器回撥,引數json就是伺服器回撥的json字串。
首先判斷泛型型別genericityType
是不是Class
型別的,然後判斷genericityType
的名字是否為String
或者Object
,是則直接在成功回撥中傳入json字串。
如果不是,則用Gson將json解析出來,實參就是genericityType
。此時解析出來的型別如果是我們剛才定義的ServerCallbackModel
,如果伺服器返回成功,那就將data返回,data的型別就是這個類的第二個型別引數,也是onSuccess
的形參型別,我們最終需要的資料。
如果伺服器返回失敗,會將錯誤傳遞給onFailed。
protected void onFailed(String error_code, String error_message)
這個方法主要是攔截錯誤,用於統一處理所有請求的錯誤。預設只判斷是否需要直接彈toast顯示錯誤資訊。
public boolean enableShowToast()
我們可以考慮是否直接將錯誤資訊彈窗提示出來,只需要重寫enableShowToast
方法,返回true
即可。
再來看看抽象方法,這個就是我們最終在具體的業務層需要重寫的方法了。
public abstract void onSuccess(V data);
伺服器返回成功的資訊後,資料會傳遞到這裡。
public abstract void onFailure(String error_code, String error_message);
錯誤經過onFailed
攔截後,會傳遞到這裡。
3 使用封裝的回撥
HttpCallback callback = new TmpCallback<ServerCallbackModel<User>,User>() {
@Override
public void onSuccess(User data) {
}
@Override
public void onFailure(String error_code, String error_message) {
}
};
API.testGet(callback);
剛才你看到ServerCallback可能還不理解為什麼這個泛型要有兩個引數,看到這裡你應該就秒懂了,其實伺服器傳回來的正確錯誤什麼的,我們並不想每個呼叫的地方都去判斷,我們這裡想要的只是最終的資料。
本文的Demo地址是我的一個開源庫,這個庫已經經過了我們公司產品大量使用者的考驗,歡迎star
和fork
,也歡迎大家提issue
。
RetrofitClient: https://github.com/Jadyli/RetrofitClient
裡面的封裝基本都是按照本文的思路寫的,當然也可以有所變化,比如有些介面沒有success之類的,直接就是上資料,那就可以使用CommonCallback。
相關文章
- Gson泛型封裝泛型封裝
- 前端自定義類事件回撥封裝前端事件封裝
- android使用Gson來解析jsonAndroidJSON
- Java中泛型的詳細解析,深入分析泛型的使用方式Java泛型
- JDBC泛型類反射封裝結果集JDBC泛型反射封裝
- LinkedList重寫(5)LinkedList簡單的封裝和增加泛型封裝泛型
- TypeScript 基本型別和泛型的使用TypeScript型別泛型
- 封裝和多型封裝多型
- [JS]回撥函式和回撥地獄JS函式
- android回撥函式Android函式
- 泛型--泛型萬用字元和泛型的上下限泛型字元
- Gson通過藉助TypeToken獲取泛型引數的型別的方法泛型型別
- Android 回撥方法的實現Android
- 也談 Android 中的回撥Android
- 關於Gson解析的使用匯總
- 更智慧的JavaScript回撥函式解析JavaScript函式
- Swift 運用協議泛型封裝網路層Swift協議泛型封裝
- 泛型類和泛型方法泛型
- .NET泛型解析(上)泛型
- .NET泛型解析(下)泛型
- Java 中泛型的全面解析Java泛型
- 深入解析Java中的泛型Java泛型
- Volley介紹JSon 和提交字串引數的封裝(StringRequest和Gson)JSON字串封裝
- Android Gson使用詳解Android
- Javascript的非同步和回撥JavaScript非同步
- Android中Retrofit的封裝使用Android封裝
- Java泛型知識點:泛型類、泛型介面和泛型方法Java泛型
- php 使用Callable Closure強制指定回撥型別PHP型別
- 解析Promise解決非同步回撥Promise非同步
- 集合框架-泛型方法的概述和使用框架泛型
- TypeScript 泛型介面和泛型類TypeScript泛型
- 封裝、繼承和多型封裝繼承多型
- C++屌屌的觀察者模式-同步回撥和非同步回撥C++模式非同步
- java學習 -- 利用類的反射和泛型自己動手寫jdbc封裝小類庫Java反射泛型JDBC封裝
- 泛型物件的使用泛型物件
- 泛型類、泛型方法、型別萬用字元的使用泛型型別字元
- Android之無法回撥onActivityResultAndroid
- C#基礎:泛型的理解和使用C#泛型