封装RxJava+Retrofit

概述

网络请求框架是Android开发中必须使用的,之前用过的网络请求框架有Android-async-http,Okhttp等,本篇想基于Retrofit+RxJava简单的封装一套网络请求框架,不能用绝对的眼光去衡量这几个框架的优缺点,没有绝对的好与坏。我们知道目前使用最少的应该是Android-async-http,最火的莫过于Retrofit,但不能简单拿的概括为他们的好坏之分。当然,适合自己的才是最好的。

简介

Retrofit: Retrofit是Square公司开发的一款正对Android 网络请求的框架。底层基于OkHttp实现,OkHttp已经得到了google官方的认可。
RxJava:提供一套异步编程的API,这套API是基于观察者模式的,而且是基于事件流链式调用的,所以使用RxJava编写的代码的逻辑会非常简洁。

Retrofit与RxJava的结合

引用库

1
2
3
4
5
6
7
8
//RxJava+Retrofit+Gson
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
implementation 'com.lzy.net:okgo:3.0.4'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

封装原理

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
//发起请求类,进行了基本的api参数配置
public class SERVICE {
private static final long DEFAULT_TIMEOUT = 30;//默认超时时间
private static Retrofit sRetrofit;
private static Gson sGson;

static {
SSLHelper.SSLParams sslParams = SSLHelper.generate(null, null, null);//证书设置,可信任全部证书

OkHttpClient httpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)//证书设置
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)//连接超时
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(new TokenInterceptor())//添加拦截器,用户身份识别
.addInterceptor(new LogInterceptor())//用于查看请求数据的Log
.addInterceptor(new DownloadInterceptor())//用于下载文件
.retryOnConnectionFailure(true)//可失败重连
.build();

sGson = new GsonBuilder()
.serializeNulls()
.create();

sRetrofit = new Retrofit.Builder()
.client(httpClient)
.baseUrl(BuildConfig.URL_HEAD)
.addConverterFactory(GsonConverterFactory.create(sGson))//天机Gson转换器,将后台数据转成可视化json
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//如果要搭配RxJava使用的话,需要将okhttp的call转成RxJava的call
.build();
}

public static Gson gson() {
return sGson;
}

public static <T> T create(Class<T> serviceClazz) {
return sRetrofit.create(serviceClazz);
}
//与用户相关的接口
public static UserService user() {
return SERVICE.create(UserService.class);
}
}
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
//用于添加用户身份token
public class TokenInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (MyApplication.getAccessToken() == null || alreadyHasAuthorizationHeader(originalRequest)) {
return chain.proceed(originalRequest);
}
Request authorised = originalRequest.newBuilder()
// token 使用URL编码
.header("token", URLEncoder.encode(MyApplication.getAccessToken(), "UTF-8"))
.build();
return chain.proceed(authorised);
}

private boolean alreadyHasAuthorizationHeader(Request originalRequest) {
return !TextUtils.isEmpty(originalRequest.header("token"));
}
}
//除了用户身份,同理也可以添加其他的配置参数,例如设备信息等等
/**
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder requestBuilder = originalRequest.newBuilder()
.header("Platform", "Android")//平台tag
// .header("Device-Token", UApplication.getIMEI())//设备信息
.method(originalRequest.method(), originalRequest.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
*/
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
/**
* 下载文件拦截器,用于获取下载进度
*/
public class DownloadInterceptor implements Interceptor {
private static final String download = "download";

@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request originalRequest = chain.request();

Request.Builder builder = originalRequest
.newBuilder()
.method(originalRequest.method(), originalRequest.body());

String load = originalRequest.header(download);
if (!TextUtils.isEmpty(load)) {
builder.removeHeader(load);
if (Boolean.parseBoolean(load)) {
Response originalResponse = chain.proceed(builder.build());
return originalResponse.newBuilder()
.body(new DownloadBody(originalResponse.body()))
.build();
}
}
return chain.proceed(builder.build());
}
}

compose的工具

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
/**
*包括线程调配,生命周期绑定,异常处理
*/
public class RxUtils {
//调配线程
public static <T> ObservableTransformer<T, T> switchThread() {
return upstream -> upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
//异常处理
public static <T> ObservableTransformer<HttpResult<T>, T> convert() {
return upstream -> upstream
.map(result -> {
if (result.success()) {//如果成功
if (result.getData() == null) {
result.setData((T) new Object());
}
return result.getData();
}
//如果失败
throw new ServerException(result.getState(), result.getMessage());
})
.onErrorResumeNext((Function<Throwable, ObservableSource<? extends T>>) throwable -> {
return Observable.error(ExceptionProcessor.handle(throwable));
});
}

public static <T, E> ObservableTransformer<HttpResult<T>, T> group(LifecycleProvider<E> provider) {
return upstream -> upstream
.compose(RxUtils.convert())
.compose(RxUtils.switchThread())
.compose(provider.<T>bindToLifecycle());
}
}

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 服务器返回值不为 SERVICE.SUCCESS 异常抛出
*/
public class ServerException extends RuntimeException {
public int state;
public String message;

public ServerException(int state, String message) {
this.state = state;
this.message = message;
}
}
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
/**
* 异常处理
*/

public class ExceptionProcessor {
//HTTP状态码
private static final int UNAUTHORIZED = 401;
private static final int FORBIDDEN = 403;
private static final int NOT_FOUND = 404;
private static final int REQUEST_TIMEOUT = 408;
private static final int INTERNAL_SERVER_ERROR = 500;
private static final int BAD_GATEWAY = 502;
private static final int SERVICE_UNAVAILABLE = 503;
private static final int GATEWAY_TIMEOUT = 504;

public static ErrorException handle(Throwable e) {
ErrorException exception = new ErrorException(e);
if (e instanceof ServerException) {// 服务器异常
exception.code = ((ServerException) e).state;
exception.message = ((ServerException) e).message;
} else if (e instanceof HttpException) {// Http异常
exception.code = Constants.HTTP_ERROR;
switch (((HttpException) e).code()) {
// 。。。 。。。
case INTERNAL_SERVER_ERROR:
exception.message = "服务器异常,请稍后再试";
break;
// 。。。 。。。
//根据业务情况而定
default:
exception.message = "网络错误";
break;
}
} else if (e instanceof JsonSyntaxException || e instanceof JsonParseException
|| e instanceof JSONException || e instanceof ParseException) {
exception.code = Constants.PARSE_ERROR;
exception.message = "JSON解析异常";
} else if (e instanceof ConnectException || e instanceof SocketTimeoutException
|| e instanceof ConnectTimeoutException) {
exception.code = Constants.NETWORK_ERROR;
exception.message = "网络连接失败";
} else {
exception.code = Constants.UNKNOWN;
exception.message = "未知错误";
}
LogUtils.e(exception);
return exception;
}
}
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
/**
* 报错内容,由上面的ExceptionProcessor返回
*/

public class ErrorException extends Exception {
public int code;
public String message;

public ErrorException(Throwable cause) {
super(cause);
message = cause.getMessage();
}

public ErrorException(Throwable cause, int code) {
super(cause);
this.code = code;
message = cause.getMessage();
}

@Override
public String toString() {
return "ErrorException{" +
"code=" + code +
", message='" + message + '\'' +
'}';
}
}
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
/**
* 响应数据模板
* 一般来说响应数据的格式为{"state":200,"message":"请求成功","data":{}}
* 也是根据业务需求而定的
*/
public class HttpResult<T> {
private int state;
private String message;
@SerializedName("result")
private T data;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
}

public String getMessage() {
return message;
}

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

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}

public boolean success() {
return state == Constants.SUCCESS;
}
}
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
/**
* LoadingObserver
* 交给界面控件处理信息
*/
public abstract class LoadingObserver<T> extends CommonObserver<T> {
private IBaseView mIBaseView;//当请求结束后,回调给界面处理(提示信息,加载动画等。。)
private boolean finish;

public LoadingObserver(IBaseView IBaseView) {
mIBaseView = IBaseView;
}

public LoadingObserver(IBaseView IBaseView, boolean finish) {
mIBaseView = IBaseView;
this.finish = finish;
}

@Override
public void onSubscribe(Disposable d) {
mIBaseView.loading(finish);
}

@Override
public void onError(Throwable e) {
if (e instanceof ErrorException) {
onError((ErrorException) e);
} else {
e.printStackTrace();
}
mIBaseView.hideLoading();
}

@Override
public void onError(ErrorException e) {
mIBaseView.toast(e.message);
}

@Override
public void onComplete() {
mIBaseView.hideLoading();
}
}

// 。。。 。。。
public interface IBaseView {
void toast(CharSequence text);

void loading(boolean finish);

void hideLoading();

Context context();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class CommonObserver<T> implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
}

@Override
public void onError(Throwable e) {
if (e instanceof ErrorException) {
onError((ErrorException) e);
} else {
e.printStackTrace();
}
}

public void onError(ErrorException e) {
//Toast.show(e.message);
}

@Override
public void onComplete() {
}
}
1
2
3
4
5
6
7
8
9
public interface UserService {
/**
* json提交
* @param request
* @return
*/
@POST("user/login")
Observable<HttpResult<UserLoginResponse>> login(@Body UserLogin request);
}

最终使用

1
2
3
4
5
6
7
8
9
//以登录接口为例
SERVICE.user().login(new UserLogin(nameStr, pwd))
.compose(RxUtils.group(this))//线程调配,绑定Activity的生命周期,防泄漏
.subscribe(new LoadingObserver<LoginBean>(this) {
@Override
public void onNext(LoginBean loginBean) {
//在此处理后天返回用户信息
}
});

总结

这一整套下来基本上能适用决大多数的请求场景,也比较灵活,随时可拆分更加个性化的功能。当然还是那句话,适合自己才是最好的。整合下来也能对RxJava的使用更加了解,RxJava用的好的话,感觉写出的代码看上去也比较炫酷。