Retrofit简单封装Callback统一错误
2018-04-04 本文已影响363人
liliLearn
前言
最近对公司网络访问Retrofit+OKHttp进行改进,分享一波自定义Callback对网络response进行处理。
Retrofit简单的使用
Retrofit执行网络请求的回调Callback,我们通过onResponse和onFailure处理网络请求成功和失败的回调执行对应的操作
官方文档:
http://square.github.io/retrofit/
public interface ApiService {
@POST("recommend/list")
Call<RecommendMessage> searchRecommend();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("XXX")
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(ApiService.class);
ApiClient.getInstance().getApiService().searchRecommend().enqueue(new Callback<RecommendMessage>() {
@Override
public void onResponse(Call<RecommendMessage> call, Response<RecommendMessage> response) {
}
@Override
public void onFailure(Call<RecommendMessage> call, Throwable t) {
}
});
统一响应体
public class BaseResponse<T> {
private int status;
private String message;
private int offset;
public T data;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "BaseResponse{" +
"status=" + status +
", message='" + message + '\'' +
", offset=" + offset +
", data=" + data +
'}';
}
}
简单的封装CallBack
public abstract class RequestCallback<T extends BaseResponse> implements Callback<T> {
public static final int SUCCESS_CODE = 0;
public abstract void success(T t);
public abstract void failure(int statusCode, ApiErrorModel apiErrorModel);
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.isSuccessful()) {
success(response.body());
}
//其他 response.code()处理....
}
@Override
public void onFailure(Call<T> call, Throwable t) {
if (t instanceof SocketTimeoutException) {//超时
} else if (t instanceof ConnectException) {//连接错误
} else if (t instanceof UnknownError) { //未找到主机
} else {//其他错误
}
}
}
封装后的网络请求:
ApiClient.getInstance().getApiService().searchRecommend().enqueue(new RequestCallback<RecommendMessage>(this) {
@Override
public void success(RecommendMessage response) {
//处理网络请求成功
if (response.getStatus() == SUCCESS_CODE) {
Log.i(TAG, "onResponse: " + response.body().toString());
} else {
//服务器返回错误信息
ToastUtil.showShortToast(this, baseResponse.getMessage());
}
}
@Override
public void failure(int statusCode, ApiErrorModel apiErrorModel) {
//处理网络连接错误
}
});
通过简单的封装整理出success和failure两个方法,使用后发现在网络成功后,还需要根据服务器返回的status进行业务处理,if层级太多而且处理繁琐,所以对Callback对网络请求回调进行处理。
if (response.getStatus() == SUCCESS_CODE) {
Log.i(TAG, "onResponse: " + response.body().toString());
} else {
ToastUtil.showShortToast(mActivity, baseResponse.getMessage());
}
继续改进
自定义完响应体之后,我们需要根据status状态,做出对应的操作,举个例子,我们的需求是
- 0 -请求成功
- 1 -请求参数错误
- 2 -未登录
- 3 -无权限访问
- 网络错误(超时、未找到主机...)
- http连接错误500 404等
所以我们继续改进Callback,把所有错误整理在一起:
创建错误信息模型
public final class ApiErrorModel {
private int code;
private String message;
private String errorType;
public ApiErrorModel(int code, String message) {
this.code = code;
this.message = message;
}
public ApiErrorModel(int code, String message, String errorType) {
this.code = code;
this.message = message;
this.errorType = errorType;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getErrorType() {
return errorType;
}
public void setErrorType(String errorType) {
this.errorType = errorType;
}
}
统一管理错误
/**
* 封装所有错误
* 分为HTTP错误
* 网络连接错误
* 服务器自定义错误
*/
public enum ApiErrorType {
/**
* http error
*/
BAD_GATEWAY(500, R.string.server_error),
NOT_FIND(404, R.string.server_error),
NETWORK_NOT_CONNECT(300, R.string.unknown_error),
UNEXPECTED_ERROR(301, R.string.unknown_error),
UNKNOWN_ERROR(304, R.string.unknown_error),
TIMEOUT_ERROR(504, R.string.timeout_error),
/**
* connection error
*/
UNKNOWN_HOST_ERROR(1000, R.string.server_error),
SOCKET_TIMEOUT_ERROR(1001, R.string.server_error),
CONNECT_ERROR(1002, R.string.server_error),;
private final int code;
private final int messageId;
public int getCode() {
return code;
}
public int getMessageId() {
return messageId;
}
public ApiErrorModel getApiErrorModel() {
Context context = App.getApplication().getApplicationContext();
return new ApiErrorModel(code, context.getString(messageId));
}
ApiErrorType(int code, @StringRes int messageId) {
this.code = code;
this.messageId = messageId;
}
}
回调处理
public abstract class RequestCallback<T extends BaseResponse> implements Callback<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<T> call, Response<T> response) {
if (response.isSuccessful()) {
BaseResponse baseResponse = response.body();
if (baseResponse == null) {
Log.e("", "解析response错误");
return;
}
if (baseResponse.getStatus() == SUCCESS_CODE) {
success(response.body());
} else {
failure(new ApiErrorModel(baseResponse.getStatus(), baseResponse.getMessage()));
}
return;
}
failure(convertHttpError(response));
}
@Override
public void onFailure(Call<T> call, Throwable t) {
ApiErrorType apiErrorType;
if (t instanceof UnknownHostException) {
apiErrorType = ApiErrorType.UNKNOWN_HOST_ERROR;
} else if (t instanceof SocketTimeoutException) {
apiErrorType = ApiErrorType.SOCKET_TIMEOUT_ERROR;
} else if (t instanceof ConnectException) {
apiErrorType = ApiErrorType.CONNECT_ERROR;
} else {
apiErrorType = ApiErrorType.UNKNOWN_ERROR;
}
failure(apiErrorType.getApiErrorModel());
}
private ApiErrorModel convertHttpError(Response response) {
ApiErrorType apiErrorType;
if (response.code() == 500) {
apiErrorType = ApiErrorType.BAD_GATEWAY;
} else if (response.code() == 404) {
apiErrorType = ApiErrorType.NOT_FIND;
} else {
apiErrorType = ApiErrorType.UNKNOWN_ERROR;
}
return apiErrorType.getApiErrorModel();
}
}
使用
public class MainActivity extends AppCompatActivity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
setEvent();
}
private void setEvent() {
button.setOnClickListener(view ->
fetchRecommendList()
);
}
private void fetchRecommendList() {
ApiClient.getInstance().getDefault().searchRecommend().enqueue(new RequestCallback<BaseResponse<List<Recommend>>>() {
@Override
public void success(BaseResponse<List<Recommend>> listBaseResponse) {
//数据处理
Log.e("data", listBaseResponse.toString());
}
@Override
public void failure(ApiErrorModel apiErrorModel) {
//错误
Toast.makeText(MainActivity.this, apiErrorModel.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
最后把网络访问中的错误都统一成一个大错误方便输出给用户
最后
简单的封装了CallBack后统一了服务器返回格式,分离了CallBack处理。在success只关注获取数据,failure处理网络连接中的异常。
由于本人水平有限,如果有错误和需要改进的地方,还希望大家多多指教,共同进步。