Android okhttp + rxJava + retorfit2使用心得

时间:2022-06-12 16:43:23

okhttp出来已经很久了,rxjava也是近两年火起来的框架,框架的使用能让我们写出更为优秀的代码,这里主要介绍square公司提供的框架,记录一下对Android新的http请求极具扩展性的写法。这里主要用到的是观察者模式,先说下概念,Observable是被观察者,Observer是观察者,
两者之间通过subcriber订阅者,由Observablesubcribe通知Observer实现交互。

对于一个普通的http get请求,这里主要进行http通信的肯定是okhttp,这点毫无疑问,因此肯定需要一个okhttp对象,于是有了下面的代码
`OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.cookieJar(new CookieManager(context)).build()

这里主要设置超时时间和Cookie的管理,这里的CookieManager是参考httpClient的CookieManager自己重写的一个类,先不去纠结。
接下来需要retorfit和rxjava框架来解决http请求和处理数据时需要的一堆代码,及子线程无法更新UI等问题,调用非常简单。先导入包,

compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

创建一个retorfit对象:
Retrofit retrofit_user = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.client(httpClient)
.build();

addConverterFactory添加Gson解析方式,这里也可以自定义解析格式,还有xml解析的Convert,String的Convert。
addCallAdapterFactory添加支持返回Observable对象,如果你在返回时用的Call,可以不去添加。
接下来核心请求方法来了,定义一个UserInterface接口,比如我们要获取用户信息,代码如下:@GET("/api/user/details")
Observable<UserDetailsInfo> getUserInfo(@Query("userId") String userId);

@GET是retrofit2.http.GET包下面的注解,参数是URL,拼接前面定义retorfit对象的baseUrl,@Query是拼接userId到这个链接后面,如baseurl为http//:10.1.22.53:8080,userid=2222,则这句url等价于http//:10.1.22.53:8080/api/user/details?userId=2222,同理@POST方法也是一样。这里返回的对象是Observable,用过java Gson的人应该知道,这种方式解析的好处在于,只要返回的json名字对应上了,不需要像Android中的JSON类去写parse方法。如服务器返回{“errCode”: 403,
“message”: “aaa”},则这里定义的UserDetailsInfo为:

   class UserDetailsInfo{
       private int errCode;
       private Stirng message;
   } 

这样就得到了服务器返回的UserDetailsInfo对象。
接下来要去创建这个接口给retorfit,
mUserInterface = retrofit_user.create(UserInterface.class);
这里源码是通过字节码去创建的方法,接下来去调用UserInterface定义的getUserInfo方法,并且订阅。
需要一个订阅者,

Subscriber<UserDetailsInfo> userSubscriber = new Subscriber<UserDetailsInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(UserDetailsInfo userDetailsInfo) {
}
};

这里是rxjava提供的api,让我们不用再通过handler去解决子线程UI更新问题,在这三个回调方法中,可以直接去更新UI,设计错误界面。
一切就绪,最后开始订阅:

` mUserInterface.getUserInfo(userid)
            .onErrorReturn(new Func1<Throwable,UserDetailsInfo>() {
                @Override
                public UserDetailsInfo call(Throwable throwable) {
                    return null;
                }
            })
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);`

这里基本是通用写法, subscribeOn参数Schedulers.io()指的是订阅通过网络IO的形式,observeOn的AndroidSchedulers.mainThread()是在主线程返回运行,subscribe是最终的订阅方法。
以上是正常情况下我们需要做的。
下面说下我在使用过程中遇到的坑:
1.对于POST请求,例如登录,后台处理登录时必须将用户名密码以json的形式,放在post请求的body中,这里需要将定义的map,转化为json数据,在接口中传到@body字段中。
2.对于json的返回数据,如果是jsonArray的,需要用list这种方式定义字段。
3.不知道服务器返回什么样的数据,要看到服务器的String信息,返回值用Response,Response是retrofit2.Response,ResponseBody是okhttp3.ResponseBody,如要修改返回字段,需要修改Subscribe对象的参数,getUserInfo接口的返回值。
遗留问题:
对于服务端返回的数据解析这块,如果返回的不是json对象或者你定义的数据结构和服务端返回的字段有错误,排错就需要改为responseBody,这里的改动牵一发而动全身,感觉不是很好用,要查看时要修改多处地方,希望能有更好的解决方案讨论下。