前言
最近對(duì)Retrofit訪問網(wǎng)絡(luò)回調(diào)進(jìn)行改進(jìn)弯汰,主要統(tǒng)一后臺(tái)API接口Json返回格式综慎,錯(cuò)誤提示模糊化。
一酬姆、統(tǒng)一后臺(tái)臺(tái)返回?cái)?shù)據(jù)格式
{
"code": 0,
"data": {},
"message": "msg"
}
public class BaseCallModel<T> {
public int code;
public String message;
public T data;
}
二嗜桌、例子
這里使用玩安卓開發(fā)API測(cè)試一波,感謝玩安卓!
1.返回Json
{
"data": [
{
"children": [],
"courseId": 13,
"id": 408,
"name": "鴻洋",
"order": 190000,
"parentChapterId": 407,
"userControlSetTop": false,
"visible": 1
},
{
"children": [],
"courseId": 13,
"id": 409,
"name": "郭霖",
"order": 190001,
"parentChapterId": 407,
"userControlSetTop": false,
"visible": 1
}
],
"errorCode": 0,
"errorMsg": ""
}
2.Model
public class BaseCallModel<T> {
private int errorCode;
private String errorMsg;
private T data;
}
public interface ApiService {
@GET("/wxarticle/chapters/json")
Call<BaseCallModel<List<WxArticle>>> getWxArticle();
}
3.以前的CallBack使用
ApiClient.getInstance().getService().getWxArticle().enqueue(new CallBack1<BaseCallModel<List<WxArticle>>>() {
@Override
public void success(BaseCallModel<List<WxArticle>> baseCallModel) {
if (baseCallModel.getErrorCode() == SUCCESS_CODE) {
①setData(baseCallModel.getData());
} else {
②Toast.makeText(CallBackTestActivity.this, baseCallModel.getErrorMsg(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void failure(String msg) {
③Toast.makeText(CallBackTestActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
4.需求分析
這里①是獲取服務(wù)器返回的數(shù)據(jù)辞色,②
和③大部分都是錯(cuò)誤輸出提示 少部分根據(jù)code做出不同的業(yè)務(wù)處理骨宠。
三、封裝CallBack
根據(jù)需求我抽象出三個(gè)方法相满,
// 訪問服務(wù)器成功直接獲取數(shù)據(jù)
public abstract void success(T t);
// 服務(wù)器錯(cuò)誤返回code 和message
public abstract void failure(int code,String msg);
// 其他錯(cuò)誤
public abstract void error(String msg);
CallBack實(shí)現(xiàn)
public abstract class CallBack<T> implements Callback<BaseCallModel<T>> {
public static final int SUCCESS_CODE = 0;
public abstract void success(T t);
public abstract void failure(int code, String msg);
public abstract void error(String msg);
@Override
public void onResponse(Call<BaseCallModel<T>> call, Response<BaseCallModel<T>> response) {
if (response.isSuccessful() && response.body() != null) {
if (response.body().getErrorCode() == SUCCESS_CODE) {
success(response.body().getData());
} else {
failure(response.body().getErrorCode()response.body().getErrorMsg());
}
}
// other
}
@Override
public void onFailure(Call<BaseCallModel<T>> call, Throwable t) {
if (t instanceof SocketTimeoutException) {//超時(shí)
error(t.getMessage());
} else if (t instanceof ConnectException) {//連接錯(cuò)誤
error(t.getMessage());
} else if (t instanceof UnknownError) { //未找到主機(jī)
error(t.getMessage());
} else {//其他錯(cuò)誤
error(t.getMessage());
}
}
}
使用
ApiClient.getInstance().getService().getWxArticle().enqueue(new CallBack2<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
//顯示數(shù)據(jù)
}
@Override
public void failure(int code,String msg) {
//提示服務(wù)器錯(cuò)誤
}
@Override
public void error(String msg) {
//其他錯(cuò)誤
}
});
當(dāng)時(shí)我就考慮到showLoadingDialog 得多處 dismissLoadingDialog层亿,抽象的方法太多了 額外的增加很多其他代碼,所以增加一個(gè)對(duì)象來保存錯(cuò)誤立美。
showLoadingDialog();
ApiClient.getInstance().getService().getWxArticle().enqueue(new CallBack2<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
dismissLoadingDialog();
//顯示數(shù)據(jù)
}
@Override
public void failure(int code, String msg) {
dismissLoadingDialog();
//提示服務(wù)器錯(cuò)誤
}
@Override
public void error(String msg) {
dismissLoadingDialog();
//其他錯(cuò)誤
}
});
再次改進(jìn)
// 訪問服務(wù)器成功直接獲取數(shù)據(jù)
public abstract void success(T t);
// 服務(wù)器錯(cuò)誤返回code 和message 和其他錯(cuò)誤
public abstract void failure(ApiErrorModel apiErrorModel);
四匿又、統(tǒng)一錯(cuò)誤提示
public final class ApiErrorModel {
public static final int SERVER_ERROR = 0;
public static final int OTHER_ERROR = 1;
private int errorType;
private int errorCode;
private String errorMsg;
public ApiErrorModel(int errorType, String errorMsg) {
this.errorType = errorType;
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public ApiErrorModel(int httpCode, int errorCode, String errorMsg) {
this.errorType = errorType;
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public boolean isOtherError() {
return getErrorType() == OTHER_ERROR;
}
public int getErrorType() {
return errorType;
}
public int getErrorCode() {
return errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
}
public abstract class CallBack<T> implements Callback<BaseCallModel<T>> {
public static final int SUCCESS_CODE = 0;
public abstract void success(T t);
public abstract void failure(ApiErrorModel apiErrorModel);
@Override
public void onResponse(Call<BaseCallModel<T>> call, Response<BaseCallModel<T>> response) {
if (response.isSuccessful() && response.body() != null) {
if (response.body().getErrorCode() == SUCCESS_CODE) {
success(response.body().getData());
} else {
failure(new ApiErrorModel(ApiErrorModel.SERVER_ERROR, response.body().getErrorCode(), response.body().getErrorMsg()));
}
}
}
@Override
public void onFailure(Call<BaseCallModel<T>> call, Throwable t) {
ApiErrorModel apiErrorModel;
if (t instanceof SocketTimeoutException) {//超時(shí)
apiErrorModel = new ApiErrorModel(ApiErrorModel.SERVER_ERROR, "超時(shí)");
} else if (t instanceof ConnectException) {//連接錯(cuò)誤
apiErrorModel = new ApiErrorModel(ApiErrorModel.SERVER_ERROR, "連接錯(cuò)誤");
} else if (t instanceof UnknownError) { //未找到主機(jī)
apiErrorModel = new ApiErrorModel(ApiErrorModel.SERVER_ERROR, "未找到主機(jī)");
} else {//其他錯(cuò)誤
apiErrorModel = new ApiErrorModel(ApiErrorModel.SERVER_ERROR, "未知錯(cuò)誤");
}
failure(apiErrorModel);
}
}
使用
ApiClient.getInstance().getService().getWxArticle().enqueue(new CallBack<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
//顯示數(shù)據(jù)
}
@Override
public void failure(ApiErrorModel apiErrorModel) {
// 提示
Toast.makeText(CallBackTestActivity.this, apiErrorModel.getErrorMsg(), Toast.LENGTH_SHORT).show();
}
});
帶Code處理
ApiClient.getInstance().getService().getWxArticle().enqueue(new CallBack<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
//顯示數(shù)據(jù)
}
@Override
public void failure(ApiErrorModel apiErrorModel) {
if (apiErrorModel.isOtherError()) {
// 提示
Toast.makeText(CallBackTestActivity.this, apiErrorModel.getErrorMsg(), Toast.LENGTH_SHORT).show();
return;
}
// 處理業(yè)務(wù)
int code = apiErrorModel.getErrorCode();
......
}
});
五、模糊化錯(cuò)誤提示
我以為就這樣完事的時(shí)候建蹄,告訴我需要模糊化錯(cuò)誤提示碌更,不能明確的告訴用戶準(zhǔn)確的錯(cuò)誤。好吧洞慎!繼續(xù)改進(jìn)
1.通過枚舉類管理所以的用戶提示錯(cuò)誤痛单。
public enum ApiErrorType {
NETWORK_NOT_CONNECT(1, R.string.network_not_connection), // 請(qǐng)檢查網(wǎng)絡(luò)連接
NETWORK_ERROR(2, R.string.network_error), // 網(wǎng)絡(luò)異常,請(qǐng)稍后再試劲腿!
SERVER_ERROR(3, R.string.server_error), // 服務(wù)器發(fā)生錯(cuò)誤
UNKNOWN_ERROR(4, R.string.unknown_error); // 未知錯(cuò)誤
private final int code;
private final int messageId;
public int getMessageId() {
return messageId;
}
ApiErrorType(int code, @StringRes int messageId) {
this.code = code;
this.messageId = messageId;
}
public ApiErrorModel getApiErrorModel() {
Context context = App.getInstance().getApplicationContext();
return new ApiErrorModel(ApiErrorModel.OTHER_ERROR, code, context.getString(messageId));
}
}
2.發(fā)生錯(cuò)誤時(shí)模糊化提示
public abstract class CompleteCallBack<T> implements Callback<BaseCallModel<T>> {
public static final int SUCCESS_CODE = 0;
public abstract void success(T t);
public abstract void failure(ApiErrorModel apiErrorModel);
@Override
public void onResponse(Call<BaseCallModel<T>> call, Response<BaseCallModel<T>> response) {
if (response.isSuccessful() && response.body() != null) {
if (response.body().getErrorCode() == SUCCESS_CODE) {
success(response.body().getData());
} else {
failure(new ApiErrorModel(ApiErrorModel.SERVER_ERROR, response.body().getErrorCode(), response.body().getErrorMsg()));
}
}
}
@Override
public void onFailure(Call<BaseCallModel<T>> call, Throwable t) {
ApiErrorType apiErrorType;
if (t instanceof UnknownHostException) {
apiErrorType = ApiErrorType.SERVER_ERROR;
} else if (t instanceof ConnectException) {
apiErrorType = ApiErrorType.NETWORK_NOT_CONNECT;
} else if (t instanceof SocketTimeoutException) {
apiErrorType = ApiErrorType.NETWORK_ERROR;
} else {
apiErrorType = ApiErrorType.UNKNOWN_ERROR;
}
failure(apiErrorType.getApiErrorModel());
}
}
3.具體使用--依舊沒變
提示
ApiClient.getInstance().getService().getWxArticle().enqueue(new CompleteCallBack<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
}
@Override
public void failure(ApiErrorModel apiErrorModel) {
Toast.makeText(MainActivity.this, apiErrorModel.getErrorMsg(), Toast.LENGTH_SHORT).show();
}
});
帶code
ApiClient.getInstance().getService().getWxArticle().enqueue(new CompleteCallBack<List<WxArticle>>() {
@Override
public void success(List<WxArticle> wxArticles) {
}
@Override
public void failure(ApiErrorModel apiErrorModel) {
if (apiErrorModel.isOtherError()) {
// 提示
Toast.makeText(MainActivity.this, apiErrorModel.getErrorMsg(), Toast.LENGTH_SHORT).show();
return;
}
// 處理業(yè)務(wù)
int code = apiErrorModel.getErrorCode();
......
}
});
總結(jié)
簡(jiǎn)單的封裝一下CallBack旭绒,分離了CallBack中業(yè)務(wù)處理。在success只關(guān)注獲取數(shù)據(jù),failure處理網(wǎng)絡(luò)連接中的異常挥吵。
由于本人水平有限重父,如果有錯(cuò)誤和需要改進(jìn)的地方,還希望大家多多指教蔫劣,共同進(jìn)步坪郭。
GitHub: