引言
上两篇文章分别提到了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)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .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) { ... }
@Override public void onComplete() {
}
public abstract void onSuccess(T result);
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()) .subscribe(new BaseObserver<BaseResponse<ResultBean>>() { @Override public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { }
@Override public void onSuccess(BaseResponse<ResultBean> result) { }
@Override public void onFail(String msg) { } }); }
|
到此已经能使用此方法进行网络请求操作了,结构清晰,代码简洁。
总结
对于网络访问的抽象与优化,实际上是个非常难的课题,在Retrofit之前,大家努力的方向基本上都是Volley/OkHttp这种围绕底层网络访问的工作。
因为越底层的东西越容易抽象,越上升到接近业务层,就越容易在纷扰的业务层中迷失。
Retrofit能精准地抓到Call网络工作对象这个关键点,并能通过一系列精巧的设计实现对这种类型“飘忽不定”的对象的自动化定制生产,着实令人赞叹。