Retrofit 2.0 + RxJava 2.0搭建简单的Android请求框架。

      哎,最近智障公司突然学某些公司,搞什么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 login(@QueryMap Map, String> loginMap);

    /**
     * retrofit2.0+rxJava2.0 结合登录
     * @param loginMap
     * @return
     */
    @POST(UrlConstants.urlHead)
    Flowable login2(@QueryMap Map, String> loginMap);

}
定义了两种方式的登录接口,代码上面也都注释,第一个就单纯的用retrofit来调接口,下面这个是两者的结合,retrofit用的这种注解的方式来进行url的设置和传参等,因为项目的请求接口全部是post的、参数以键值对的形式传入,将接口定义成了以上的这种形式。当然,get请求方式直接@Get,参数也支持各种类型@query、@path、@ body等等。

下面定义一个单例:

/**
 * 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 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());
      }
   });
}
上面这种方式只用retrofit的异步调用接口,返回的结果response中,就是直接解析好的结果。

这边有个,就是不管解析成功和失败,都会进入onResponse方法,只不过解析出错了, response为null,所以在这边要进行一些处理。

下面用RxJava 的形式来调用接口:

private void loginFlowable(){
   LoginParam param = new LoginParam();
   Flowable 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());
            }
         });

}
在用Rxjava形式调用时,要注意线程切换,耗时的操作肯定不能再主线程,

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() {
            @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());
            }
         });
在上面用Rxjava请的过程中,我只用了一个map操作符变换,修改了其中的一个属性,也可以用其它操作符进行别的操作来满足开发中需求。

这个跟上面只用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才刚开始接触没多久,但是觉的这种链式的结构确实写起来很舒服,以后还得多多应用,熟练起来。这确实是个很好用的东西,当然在撸代码的过程中,也不是所有的地方都得使用,具体要不要用还是要根际实际需求来~~~~~~~~~~


你可能感兴趣的:(android,移动开发)