Retrofit2.0+RxJava初步
之前看了StormZhang的网络请求哪家强, 里面有详细的主流网络请求框架对比,
最近在自己的项目中引入了Retrofit2.0, 同时配合使用RxJava,替换了原先OkHttp。
本文对于基本的实现做了总结,也有一些碰到的问题,以及Retrofit2.0相对1.0版本的一些变化
依赖项
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:+'
compile 'com.squareup.retrofit2:adapter-rxjava:+'
可以看到, 除了RxAndroid, RxJava, Retrofit依赖,另外还有两个: converter-gson, adapter-rxjava. 下面会做详细介绍。
定义请求接口
通过注解的方式,为每个请求声明请求的类型(Get, Post, Delete ...) , 地址, 以及参数等, 如下:
public interface CommentService{
@GET("shots/{id}/comments")
Observable<Comment[]> getComments(@Path("id") int id,
@Query("page") String page);
}
这里需要注意的是, 2.0中地址格式的变化:
Correct: Base URL: http://example.com/api/
Endpoint: foo/bar/ Result: http://example.com/api/foo/bar/
而1.0中Base URL最后的“/”是在Endpoint中。
创建Retrofit实例
Retrofit提供了Builder和工厂模式来创建对应的请求实例,如下:
public static <T> T createRetrofitService(final Class<T> clazz) {
String GET_API_URL = "https://api.dribbble.com/v1/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GET_API_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(clazz);
}
我们可以看到, 在build过程中,增加了GsonConverterFactory和RxJavaCallAdapterFactory, 分别是在上述引用依赖时候的内容, 下面我们来看看Retrofit提供的这两个工厂类:
- GsonConverterFactory
顾名思义,它是一个Json数据转化类,其中Gson是目前应用最广泛的Json解析库,所以Retrofit引入它就是为了将数据转化封装到内部实现,也减少了我们的工作量。
当然1.0的Retrofit还没有引入, 我们会看到1.0是使用RestAdapter来实现请求结果转化的,下面是一段官方解释:
But in Retrofit 2.0, Converter is not included in the package anymore. You need to plug a Converter in yourself or Retrofit will be able to accept only the String result. As a result, Retrofit 2.0 doesn't depend on Gson anymore.
If you want to accept json result and make it parse into DAO, you have to summon Gson Converter as a separate dependency.
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' And plug it in through addConverterFactory. Please note that RestAdapter is now also renamed to Retrofit.
- RxJavaCallAdapterFactory
这个类是为了与RxJava衔接而提供的, 如果不添加这个实现, 直接使用RxJava的观察者模式,会得到如下报错:
Unable to create call adapter for class
进一步封装
通过上述“定义接口”, “创建实例”, 我们已经可以实现一个完整的请求,并将结果输出, 但是, 这样的请求并不是非常灵活, 例如,如何为每个请求中添加header信息?(我们在项目中经常把token作为每次请求的必带参数),如果按照上述方法,得在每个接口中申明header参数,显然是不太合理。
Retrofit当然也会考虑这些问题, 可以实现自定义http客户端,我们在builder之前进行自定义,代码:
public static <T> T createRetrofitService(final Class<T> clazz) {
String GET_API_URL = "https://api.dribbble.com/v1/";
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder()
.method(original.method(), original.body())
//添加请求头部信息
.header("Authorization", "Bearer " + ServiceConfig.ACCESS_TOKEN);
return chain.proceed(builder.build());
}
});
OkHttpClient okHttpClient = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GET_API_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(clazz);
}
这样,就实现了每次请求都带了Header信息。以此为例, 我们还可以进一步实现请求缓存等功能, 后续再更新...
另外, RxJava的监听线程等方法也可以封装:
public static <T> void toSubscribe(Observable<T> o, Subscriber<T> s) {
o.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s);
}
完成请求
有了以上的封装,以下是我在UI层调用网络请求的代码:
ServiceFactory.toSubscribe(getObservable(), new Subscriber<Shot[]>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
requestFailed();
}
@Override
public void onNext(Shot[] resultList) {
requestSuccess(resultList);
}
});
Observable<Shot[]> getObservable() {
return ServiceFactory.createRetrofitService(
DribService.ShotService.class).getShots(String.valueOf(mPage), mQueryMap);
}
总结
引入了Retrofit2.0 + RxJava, 确实使整个项目结构更加清晰, 而且也省去了原先OkHttp封装的工作。下面是我自己项目的地址,里面有更加详细的内容,后续也会进一步做一些更新,例如请求缓存等内容。
https://github.com/binqiangsun/DribbblApp
刚刚接触Retrofit,如果上述有错误的地方,欢迎交流指正,谢谢~