RxJava、Retrofit结合使用进行网络请求

引言

上两篇文章分别提到了retrofit以及RxJava的使用以及好处,这篇文章开始介绍它们的结合使用

首先引入相关的包

implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' //rxjava
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //retrofit
implementation 'com.squareup.retrofit2:retrofit-converters:2.9.0' //rxjava2对应适配包(二选1)
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' //rxjava3对应适配包(二选1)
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.9.1'

创建retrofit接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Observable;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Query;
import retrofit2.http.Url;

public interface IRetrofitApi {
@FormUrlEncoded
@Headers({"Domain-Name: api"})
@POST("payment/alipay")
Observable<Response<String>> alipay(@Field("user_id") String userId, @Field("money") int money);
}

其中RxJava的Observable替换了retrofit的Call类型,Response泛型String可替换成返回的数据类型,我这里因为要解密返回密文所以使用String接收

创建retrofit接口调用类

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
public class RetrofitSource {
private IRetrofitApi api;
private static RetrofitSource retrofitSource = null;

public static synchronized RetrofitSource instance(){
if(retrofitSource == null) {
retrofitSource = new RetrofitSource();
}
return retrofitSource;
}

public RetrofitSource() {
OkHttpClient mClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
try {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Accept-Charset", "UTF-8") //统一添加请求头
.addHeader("Accept", " application/json");

Request request = builder.build();
return chain.proceed(request);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(AppConfig.host + API_VERSION)
// .addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) //用于上面提到的的Retrofit
.addConverterFactory(StringConverterFactory.create())
.client(mClient)
.build();
api = retrofit.create(IRetrofitApi.class);
}

}

初始化解析

初始化OkHttpClient

主要是添加拦截器来修改请求的配置

初始化retrofit及retrofitApi

.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) 

用于上面提到的的Retrofit的Call转换成RxJava的Observable。

.addConverterFactory(StringConverterFactory.create())

用于将请求结果的解析成对应类型数据。

解析Gson可以使用

.addConverterFactory(GsonConverterFactory.create())

不要忘记单独添加依赖

compile 'com.squareup.retrofit2:converter-gson:2.9.0'

请求方法

1
2
3
public Observable<Response<String>> alipay(String userId, int money) {
return this.api.alipay(userId, money);
}

初始化时Retrofit已经用动态代理生成Observable网络请求对象,所以这里调用接口方法能直接进行网络接口请求

使用RxJava调用接口

RxJava调用可以简化代码使代码更清晰,以及能切换线程的方法,在android中实现结果返回时操作UI线程。省去了Android handler或者AsyncTask的复杂创建,抽象了HTTP请求接口,使代码结构更清楚

自定义观察者基类

创建一个观察者抽象基类实现Observer接口中onSubscribe onNext onComplete方法,泛型是返回的数据类型,新增了自己的两个回调接口方法

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
public abstract class BaseObserver<T> implements Observer<Response<String>> {

private T result; //返回结果

public T getResult() {
return result;
}

public void setResult(T result) {
this.result = result;
}

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

}

@Override
public void onNext(@NonNull Response<String> stringResponse) {
...
//这边进行数据的封装处理
//成功回调onSuccess(result)接口
//失败回调onFail(msg)接口
}

@Override
public void onComplete() {

}

/**
* 成功回调
* @param result
*/
public abstract void onSuccess(T result);

/**
* 错误回调
* @param msg
*/
public abstract void onFail(String msg);

}

RetrofitSource调用接口并传入Observer对象处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
RetrofitSource.instance().alipay(uid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) //切换andoirdUI线程操作
.subscribe(new BaseObserver<BaseResponse<ResultBean>>() {
@Override
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
//请求失败回调
}

@Override
public void onSuccess(BaseResponse<ResultBean> result) {
//获取结果并进行UI操作
}

@Override
public void onFail(String msg) {
//返回结果处理失败回调
}
});
}

到此已经能使用此方法进行网络请求操作了,结构清晰,代码简洁。

总结

对于网络访问的抽象与优化,实际上是个非常难的课题,在Retrofit之前,大家努力的方向基本上都是Volley/OkHttp这种围绕底层网络访问的工作。
因为越底层的东西越容易抽象,越上升到接近业务层,就越容易在纷扰的业务层中迷失。
Retrofit能精准地抓到Call网络工作对象这个关键点,并能通过一系列精巧的设计实现对这种类型“飘忽不定”的对象的自动化定制生产,着实令人赞叹。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!