哎,最近智障公司突然学某些公司,搞什么996,然而要搞的项目的需求和UI都还没出来,没事还要蹲到很晚,着实很痛苦哎。。。。之前都没怎么写过博客,正好趁着这段有空的时间来写一遍博客,记录一下自己研究的Rxjava和retrofit一些相关的东西~
RxJava和Retrofit已经出来很长时间,现在的很多android App都已经被这两个东西占领,现在在弄的这个项目正好就我一个人负责,于是就决定把中东西的老掉牙的网络请求框架给换掉,自己来搭建一个简单的网络请求框架。现在的Rxjava 和 Retrofit 都已经到了2.0,于是自己花了点时间去了解一下它们的1.x和2.x,然后开始搭建自己的网络请求框架。
开始搭建之前,肯定得先引入需要的一些库,gridle 的配置如下:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'io.reactivex.rxjava2:rxjava:2.0.1' compile 'com.squareup.retrofit2:retrofit:2.2.0' compile 'com.squareup.retrofit2:converter-gson:2.2.0' compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'如上图,rxjava、rxandroid和retrofit 全部都是2.x,converter-gson就是json的转换类,最后那个adapter是国外的一个大神弄出来,这个是结合retrofit和rxjava 的关键。
先面先定义一个接口类:
/** * Created by rouzi on 2017/4/7. * 所有接口的入口 */ public interface ApiService { /** * retrofit2.0登录 * @param loginMap * @return */ @POST(UrlConstants.urlHead) Call定义了两种方式的登录接口,代码上面也都注释,第一个就单纯的用retrofit来调接口,下面这个是两者的结合,retrofit用的这种注解的方式来进行url的设置和传参等,因为项目的请求接口全部是post的、参数以键值对的形式传入,将接口定义成了以上的这种形式。当然,get请求方式直接@Get,参数也支持各种类型@query、@path、@ body等等。login(@QueryMap Map , String> loginMap); /** * retrofit2.0+rxJava2.0 结合登录 * @param loginMap * @return */ @POST(UrlConstants.urlHead) Flowable login2(@QueryMap Map , String> loginMap); }
下面定义一个单例:
/** * Created by rouzi on 2017/4/7. *接口管理类 */ public class ApiManager { private ApiService apiService; private static ApiManager apiManager; public synchronized static ApiManager getInstance(){ if(apiManager == null){ apiManager = new ApiManager(); } return apiManager; } public ApiService getApiService(){ if(apiService == null){ OkHttpClient okClient = new OkHttpClient.Builder().build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(UrlConstants.baseUrl) .client(okClient) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); apiService = retrofit.create(ApiService.class); } return apiService; } }上面这个类作为接口的统一入口,在getApiService()方法中,定义了一个OkhttpClent,这个是retrofit强制依赖的
addCallAdapterFactory(RxJava2CallAdapterFactory.create())这句是讲RxJava和retrofit结合起来。
addConverterFactory(GsonConverterFactory.create())
这个是添加gson解析库,直接对请求结果进行json解析。
下面就可以用起来了:
private void loginRetrofit(){ LoginParam param = new LoginParam(); Call上面这种方式只用retrofit的异步调用接口,返回的结果response中,就是直接解析好的结果。call = ApiManager.getInstance().getApiService().login(param); call.enqueue(new Callback () { @Override public void onResponse(Call call, Response response) { if(!response.body().newLoginResponseMsg.success){ showMessage1(response.body().newLoginResponseMsg.result_code_msg); } } @Override public void onFailure(Call call, Throwable t) { Log.d("retrofitLoginFailure", t.getMessage()); showMessage1(t.getMessage()); } }); }
这边有个,就是不管解析成功和失败,都会进入onResponse方法,只不过解析出错了, response为null,所以在这边要进行一些处理。
下面用RxJava 的形式来调用接口:
private void loginFlowable(){ LoginParam param = new LoginParam(); Flowable在用Rxjava形式调用时,要注意线程切换,耗时的操作肯定不能再主线程,flowable = ApiManager.getInstance().getApiService().login2(param); flowable.subscribeOn(Schedulers.newThread()) .map(new Function , LoginResponse>() { @Override public LoginResponse apply(LoginResponse loginResponse) throws Exception { loginResponse.newLoginResponseMsg.result_code_msg = "密码错误,蛤蟆皮"; return loginResponse; } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new ApiSubscriberCallBack () { @Override public void onSuccess(LoginResponse loginResponse) { if(!loginResponse.newLoginResponseMsg.success){ showMessage1(loginResponse.newLoginResponseMsg.result_code_msg); } } @Override public void onFailure(Throwable t) { showMessage1(t.getMessage()); } }); }
subscribeOn(Schedulers.newThread)这个方法就是制定被管擦事件在子线程中执行,
observeOn(AndroidSchedulers.mainThread)这个方法让消费事件在主线程进行。
上面的 ApiSubscriberCallBack 类是继承了Subscriber类的:
/** * Created by rouzi on 2017/4/11. * 回调的基类 */ public abstract class ApiSubscriberCallBack<T> implements Subscriber<T> { @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } @Override public void onNext(T t) { onSuccess(t); } @Override public void onError(Throwable t) { onFailure(t); } @Override public void onComplete() { } public abstract void onSuccess(T t); public abstract void onFailure(Throwable t); }以为调接口,我们基本是只关注onNext() 和 onError()方法,所以稍微修改一下,改成我们经常用的回调形式:
.subscribe(new ApiSubscriberCallBack在上面用Rxjava请的过程中,我只用了一个map操作符变换,修改了其中的一个属性,也可以用其它操作符进行别的操作来满足开发中需求。() { @Override public void onSuccess(LoginResponse loginResponse) { if(!loginResponse.newLoginResponseMsg.success){ showMessage1(loginResponse.newLoginResponseMsg.result_code_msg); } } @Override public void onFailure(Throwable t) { showMessage1(t.getMessage()); } });
这个跟上面只用retrofit一样,返回的response如果解析错误,也会返回一个null,所以要注意这个坑。
在我们调试的时候经常需要看接口的请求链接和返回结果的日志,那么就可以在OkHttpClient中设置一个拦截器Interceptor来做这些事情:
class MyInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Log.d("retrofitRequest", String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); ResponseBody body = response.peekBody(1024*1024); String ss = body.string(); Log.d("retrofitResponse", ss); return response; } }先定义一个Interceptor,里面的拿到request,就能进行很多设置,具体不讲解了,然后在okhttpClient中设置一下
OkHttpClient okClient = new OkHttpClient.Builder().addInterceptor(new MyInterceptor()).build();这样,你就能在Log中,看到你想要的东西了,到这基本就弄完了。
站在巨人的肩膀上,自己也能弄出一个框架(哈哈哈哈哈,这当然离真正的框架差远了,但至少迈出了搭建框架的第一步O(∩_∩)O哈哈~)
Rxjava才刚开始接触没多久,但是觉的这种链式的结构确实写起来很舒服,以后还得多多应用,熟练起来。这确实是个很好用的东西,当然在撸代码的过程中,也不是所有的地方都得使用,具体要不要用还是要根际实际需求来~~~~~~~~~~