Android开发

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状态,做出对应的操作,举个例子,我们的需求是

所以我们继续改进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处理网络连接中的异常。

由于本人水平有限,如果有错误和需要改进的地方,还希望大家多多指教,共同进步。

上一篇下一篇

猜你喜欢

热点阅读