RXjava+Retrofit封裝:對觀察者Observer進行封裝,實現代碼複用和拓展

在使用rxjava+retrofit處理網絡請求的時候,一般會採用對觀察者進行封裝,實現代碼複用和拓展

public class FObserver<T> implements Observer<T> {

    private Disposable mDisposable;

    private ResultCallback mCallback;

    public FObserver(ResultCallback callback) {
        this.mCallback = callback;
    }

    @Override
    public void onSubscribe(Disposable d) {
        this.mDisposable = d;
    }

    @Override
    public void onNext(T t) {
        try {
            doOnNext(t);
        } catch (Exception e) {
//            FLog.e(e);
            onError(e);
        }

        disposeObserver();
    }

    public void doOnNext(T t) throws Exception {
        if (mCallback != null) {
            mCallback.onResult(t);
        }
    }

    @Override
    public void onError(Throwable e) {
//        FLog.d("onError + " + e);
        FResult result = new FResult(FError.GENERAL_ERROR);
        result.setExceptionClassName(e.getClass().getSimpleName());

        if (e instanceof HttpException) {
            result = parseHttpException((HttpException) e);
        } else if (e instanceof NetworkErrorException
                || e instanceof SocketTimeoutException
                || e instanceof ConnectException
                || e instanceof SocketException
                || e instanceof UnknownHostException
                || e instanceof NoRouteToHostException
                || e instanceof TimeoutException) {
            result.setErrorCode(FError.NETWORK_ERROR.getValue());
        }else if(e instanceof JsonSyntaxException){
            result.setErrorCode(FError.JSON_PARSER_ERROR.getValue());
        }
        try {
            onError(result);
        } catch (Throwable throwable) {
            FLog.e(throwable);
        } finally {
            disposeObserver();
        }
    }

    private FResult parseHttpException(HttpException httpException) {
        FResult result = new FResult(FError.HTTP_ERROR);
        try {
            result.setHttpCode(httpException.code());
            result.setExceptionClassName(httpException.getClass().getSimpleName());
            String errorBodyStr = httpException.response().errorBody().string();
            JsonObject errorBody = new Gson().fromJson(errorBodyStr, JsonObject.class);
            result.setTimestamp(getJsonValue(errorBody, "timestamp"));
            result.setStatus(getJsonValue(errorBody, "status"));
            result.setMessage(getJsonValue(errorBody, "error"));
            result.setException(getJsonValue(errorBody, "exception"));
            result.setException(getJsonValue(errorBody, "message"));
            result.setPath(getJsonValue(errorBody, "path"));
        } catch (IOException | JsonIOException e) {
            FLog.e(e);
        }

        return result;
    }

    public static String getJsonValue(JsonObject object, String elementName) {
        if (object == null || TextUtils.isEmpty(elementName)) {
            return "";
        }
        if (!object.has(elementName)) {
            return "";
        }
        if (object.get(elementName).isJsonNull()) {
            return "";
        }

        return object.get(elementName).getAsString();
    }

    public void onError(FResult result) {
        if (mCallback != null) {
            mCallback.onError(result);
        }
    }

    @Override
    public void onComplete() {
        disposeObserver();
    }

    private void disposeObserver() {
        try {
            if (mDisposable != null) {
                mDisposable.dispose();
            }
        } catch (Exception ex) {
            FLog.e("disposeObserver", ex);
        }
    }
}
public interface ResultCallback<T> {
    void onError(FResult result);

    void onResult(T result);
}
public class FResult {
    private int errorCode;
    private String exceptionClassName;

    //only HttpException
    private int httpCode;

    //FErrorDTO content
    private String timestamp;
    private String status;
    private String error;
    private String exception;
    private String message;
    private String path;

    public FResult(FError ferror) {
        this.errorCode = ferror.getValue();
        this.message = ferror.name();
    }

    public FResult(int errorCode, String message) {
        this.errorCode = errorCode;
        this.message = message;
    }

    public FResult(int errorCode, String message, String path, String status, String timestamp) {
        this.errorCode = errorCode;
        this.message = message;
        this.path = path;
        this.status = status;
        this.timestamp = timestamp;
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }

    public void setExceptionClassName(String exceptionClassName) {
        this.exceptionClassName = exceptionClassName;
    }

    public void setHttpCode(int httpCode) {
        this.httpCode = httpCode;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public void setError(String error) {
        this.error = error;
    }

    public void setException(String exception) {
        this.exception = exception;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setPath(String path) {
        this.path = path;
    }

    private String geTime(String timestamp) {
        if (timestamp == null) {
            return "";
        }
        try {
            Date date = new Date(Long.decode(timestamp));
            return date.toLocaleString();
        } catch (Exception e) {
            FLog.e(e);
        }
        return "";
    }

    public int getErrorCode() {
        return errorCode;
    }

    public String getExceptionClassName() {
        return exceptionClassName;
    }

    public int getHttpCode() {
        return httpCode;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public String getStatus() {
        return status;
    }

    public String getError() {
        return error;
    }

    public String getException() {
        return exception;
    }

    public String getMessage() {
        return message;
    }

    public String getPath() {
        return path;
    }

    @Override
    public String toString() {
        return "FResult{" +
                "errorCode=" + errorCode +
                ", exceptionClassName='" + exceptionClassName + '\'' +
                ", httpCode=" + httpCode +
                ", timestamp='" + timestamp + '\'' +
                ", status='" + status + '\'' +
                ", error='" + error + '\'' +
                ", exception='" + exception + '\'' +
                ", message='" + message + '\'' +
                ", path='" + path + '\'' +
                '}';
    }
}

應用

api.getRadioListFree(putBaseMap(request.toMap())).subscribe(
                new FObserver<RadioListFreeRes>(callback));
//api
@GET(Constants.BASE_PATH + Constants.SERVICE_getLyric)
    Observable<RadioListFreeRes> getRadioListFree(@QueryMap Map<String, String> map);

關於disposable
rxjava雖然好用,但是總所周知,容易遭層內存泄漏。也就說在訂閱了事件後沒有及時取閱,導致在activity或者fragment銷燬後仍然佔用着內存,無法釋放。而disposable便是這個訂閱事件,可以用來取消訂閱
在oError和onComplete後調用disposable.dispose();

參考鏈接:https://www.cnblogs.com/zhujiabin/p/9294263.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章