处理前

使用r2+r2组合 以下代码很常见

只有返回的数据能解析成即有格式时 会走onNext 我们往往还要进一步判断
常见的是判断成功/失败的标志字段

对于onError 我们一般都是弹出提示

如果服务端返还格式不规范也不会走onNext

异常处理我们显得很无力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ApiManager.getApi().XXXXXXX(ObjectHelper.toMap(quickDeliverDTO))
.compose(this.bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ApiResult<String>>() {
@Override
public void onComplete() {

}

@Override
public void onError(Throwable e) {


}

@Override
public void onSubscribe(@NonNull Disposable d) {

}

@Override
public void onNext(ApiResult<String> stringApiResult) {

}
});

我们希望可以。。。

1.自定义错误处理
2.成功/失败标志不要手动判断 成功走单独回调
3.失败时 默认方法提示错误,不用每次手写弹窗
4.没有网络连接时,不发起请求,走失败回调
5.保留原有回调 应对特殊情况

自定义Converter 捕获异常

CustomGsonResponseBodyConverter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;

CustomGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}

@Override
public T convert(ResponseBody value) throws IOException {
String response = value.string();
HttpStatus httpStatus = gson.fromJson(response, HttpStatus.class);
if (!httpStatus.isSuccess()) {
value.close();
throw new ApiException(httpStatus.getCode(), httpStatus.getMessage());
}

MediaType contentType = value.contentType();
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
InputStream inputStream = new ByteArrayInputStream(response.getBytes());
Reader reader = new InputStreamReader(inputStream, charset);
JsonReader jsonReader = gson.newJsonReader(reader);

try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}

CustomGsonRequestBodyConverter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
final class CustomGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");

private final Gson gson;
private final TypeAdapter<T> adapter;

CustomGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}

@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}

CustomGsonResponseBodyConverter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;

CustomGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}

@Override
public T convert(ResponseBody value) throws IOException {
String response = value.string();
HttpStatus httpStatus = gson.fromJson(response, HttpStatus.class);
if (!httpStatus.isSuccess()) {
value.close();
throw new ApiException(httpStatus.getCode(), httpStatus.getMessage());
}

MediaType contentType = value.contentType();
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
InputStream inputStream = new ByteArrayInputStream(response.getBytes());
Reader reader = new InputStreamReader(inputStream, charset);
JsonReader jsonReader = gson.newJsonReader(reader);

try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}

其他相关类

HttpStatus.java
对应接口异常时的返回,不关心返回数据的解析,只解析code,message

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HttpStatus {
@SerializedName("resultCode")
private int mCode;
@SerializedName("resultMsg")
private String mMessage;

public int getCode() {
return mCode;
}

public String getMessage() {
return mMessage;
}

}

ApiException.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class ApiException  extends RuntimeException {
private int mErrorCode;
private String errorMessage;

public String getErrorMessage() {
return errorMessage;
}

public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}

public int getErrorCode() {
return mErrorCode;
}

public void setErrorCode(int errorCode) {
mErrorCode = errorCode;
}

public ApiException(int errorCode, String errorMessage) {
super(errorMessage);
this.mErrorCode = errorCode;
this.errorMessage = errorMessage;
}


}

自定义 Observer

实现常用处理 免去复写

DisposableObserver 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

public abstract class BaseDisposableObserver<T> extends DisposableObserver<ApiResult<T>> {


private final int RESPONSE_CODE_OK = 1; //自定义的业务逻辑,成功
private final int RESPONSE_CODE_FAILED = 2; //返回数据失败,严重的错误
private Context mContext;
private static Gson gson = new Gson();
private int errorCode;
private String errorMsg = "未知的错误!";

public BaseDisposableObserver(Context context) {
this.mContext = context;
}

@Override
protected void onStart() {
if (!NetworkUtils.isConnected()) {
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "没有网络,请检查网络连接";
onFailure(errorCode,errorMsg);
}
}

public abstract void onSuccess(T t);


@Override
public void onNext(@NonNull ApiResult<T> response) {
if (response.getResultCode() == RESPONSE_CODE_OK) {
onSuccess(response.getObject());
} else {
onFailure(response.getResultCode(), response.getResultMsg());
}

}


@Override
public void onError(@NonNull Throwable t) {
L.d(t.getMessage());

if (t instanceof HttpException) {
HttpException httpException = (HttpException) t;
errorCode = httpException.code();
errorMsg = httpException.getMessage();
getErrorMsg(httpException);
} else if (t instanceof ApiException) {
ApiException exception = (ApiException) t;
errorCode = exception.getErrorCode();
errorMsg = exception.getErrorMessage();
} else if (t instanceof SocketTimeoutException) { //VPN open
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "服务器响应超时";
} else if (t instanceof ConnectException) {
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "网络连接异常,请检查网络";
} else if (t instanceof RuntimeException) {
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "运行时错误";
} else if (t instanceof UnknownHostException) {
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "无法解析主机,请检查网络连接";
} else if (t instanceof UnknownServiceException) {
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "未知的服务器错误";
} else if (t instanceof IOException) { //飞行模式等
errorCode = RESPONSE_CODE_FAILED;
errorMsg = "没有网络,请检查网络连接";
}
onFailure(errorCode, errorMsg);


}


@CallSuper
public void onFailure(int code, String message) {
switch (code) {

case 4:
//退回到登录页面
Intent intent = new Intent();
intent.setClass(mContext, LoginActivity.class);
mContext.startActivity(intent);
break;
}
Toast.makeText(mContext, message + " code=" + code, Toast.LENGTH_SHORT).show();
}

private void getErrorMsg(HttpException httpException) {
}

@Override
public void onComplete() {

}
}

Observer 实现也类似

1
2
3
4
public abstract class BaseObserver <T> implements Observer<ApiResult<T>> {

.....
}

代码使用

1
2
3
4
5
6
7
8
9
10
11
12
13
ApiManager.getSmartApi().login(mNameEdit.getText().toString(), mPassEdit.getText().toString())
.compose(this.bindToLifecycle())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseDisposableObserver<String>(getActivity()) {
@Override
public void onSuccess(String s) {
startActivity(new Intent(getActivity(),MainActivity.class));
BasePreference.getInstance().saveToken(s);
}


}) ;

1.没网络时 不请求直接onFailure

2.数据解析成功且标志位置成功时 onSuccess

3.其他走onFailure

onFailure默认弹出提示框提示错误代码 错误信息
token失效时返回登录页面

最重要的是默认onFailure处理都不用另写了!

当然也可以子类实现 不用默认处理 Observer的默认回调都在