Android-Rxjava&retrofit&daggerAndroid进阶之旅网络请求框架

RxJava+Retrofit 史上最精简封装(RxHttpUt

2017-06-28  本文已影响2442人  lygttpod
我们都是知道Android开发必不可少的网络请求框架这几年经历了几次变更 android-async-http---->Volley、XUtils---->OkHttp---->Retrofit,这两年RxJava的流行让Retrofit着实火了一把,身为合格的Android开发人员要是对它不了解还真有点说不过去。

开篇

我是在去年的时候开始接触RxJava+Retrofit的,那时候还是RxJava1.x的版本,当时根据需求自己简单封装了一个网络库RxHttpUtils,因为只是针对公司项目的需求做的封装,所以有些局限性。可拓展性也不是很好(但是针对公司项目已经够用了),就这样那次封装之后就没怎么修改过相关代码了。
近期正好又开了新项目,网络请求这块后台有些变化,之前的网络框架不能满足了,加上RxJava2都已经出来了,所以就有了基于RxJava2重新封装的想法,这几天对RxHttpUtils1.x重构了一下,需要了解怎么使用的可以直接看RxHttpUtils 2.x里边有详细的使用说明,而且我也建议先看看使用说明加上demo自己试试看看,在我看来想要了解一件事必须先知道怎么去使用它,之后才是深入了解,解剖实现原理。
目录结果.png

介绍

原始RxJava+Retrofit的请求

正式开始之前我们先看看原始的Retrofit是怎么使用

                //先要构建出okHttpClient
                OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
                okHttpBuilder.readTimeout(10, TimeUnit.SECONDS)
                        .writeTimeout(10,TimeUnit.SECONDS)
                        .connectTimeout(10,TimeUnit.SECONDS)
                        .........省略n多配置

                 OkHttpClient okHttpClient = okHttpBuilder.build();

                //构建出Retrofit实例
                Retrofit.Builder builder = new Retrofit.Builder();
                Retrofit retrofit = builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .baseUrl("your_upload_url")
                        .client(okHttpClient)
                        .build();

                retrofit
                        .create(ApiService.class)
                        .getTop250(5)
                        .subscribeOn(Schedulers.io())//请求在IO线程中
                        .observeOn(AndroidSchedulers.mainThread())//回调在主线线程
                        .subscribe(new Observer<Top250Bean>() {
                            @Override
                            public void onSubscribe(@NonNull Disposable d) {
                                
                            }

                            @Override
                            public void onNext(@NonNull Top250Bean top250Bean) {
                                      //请求成功
                            }

                            @Override
                            public void onError(@NonNull Throwable e) {
                                      //请求失败
                            }

                            @Override
                            public void onComplete() {

                            }
                        });

以上就是原始RxJava+Retrofit的请求方式,需要先构建出OKHttpClient,在实例化Retrofit最后才是create并且subscribe,中间还有线程切换的配置,大眼一看一个简单的请求写了这么多代码,这么麻烦,怎么一点也发现不了它的好处呐。别着急,好的东西只要亲身体验过后才知道。

我们总不能每次请求都写这么多代码吧,而且还都是重复的代码,既然是重复的代码我们就能把他抽离出去,进行简单的封装,使用的时候减少不必要的代码量。下边开始介绍如何封装。

封装

步骤 1、封装OkHttpClient 2、封装Retrofit 3、对线程切换的封装 4、对Observer封装

1、首先是要构建一个OkHttpClient,我们就新建一个类单独出来它

public class HttpClient {

    private static HttpClient instance;

    private OkHttpClient.Builder builder;

    public HttpClient() {
        builder = new OkHttpClient.Builder();
    }

    public static HttpClient getInstance() {

        if (instance == null) {
            synchronized (HttpClient.class) {
                if (instance == null) {
                    instance = new HttpClient();
                }
            }

        }
        return instance;
    }


    public OkHttpClient.Builder getBuilder() {
        return builder;
    }

}

以上代码简单到根本需要注释,只是实例化出来okhttpclient,使用builder的方式是为了后边使用的时候方便定制自己的配置。

2、构建出Retrofit,我们也单独新建一个文件处理(代码结果和HttpClient 如出一辙)
public class RetrofitClient {

   private static RetrofitClient instance;

   private Retrofit.Builder mRetrofitBuilder;
   private OkHttpClient.Builder mOkHttpBuilder;

   public RetrofitClient() {

       mOkHttpBuilder = HttpClient.getInstance().getBuilder();

       mRetrofitBuilder = new Retrofit.Builder()
               .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
               .addConverterFactory(GsonConverterFactory.create())
               .client(mOkHttpBuilder.build());
   }


   public static RetrofitClient getInstance() {

       if (instance == null) {
           synchronized (RetrofitClient.class) {
               if (instance == null) {
                   instance = new RetrofitClient();
               }
           }
       }
       return instance;
   }


   public Retrofit.Builder getRetrofitBuilder() {
       return mRetrofitBuilder;
   }

   public Retrofit getRetrofit() {
       return mRetrofitBuilder.client(mOkHttpBuilder.build()).build();
   }

}
3、对线程切换的封装

通过对最原始请求的分析可以看到每次都要对线程切换进行配置,是不是可以把它在进行封装呐,答案肯定是能,这里就要用到RxJava操作符的相关知识了,不了解的可以去搜一下哦,毕竟这样的文章已经有一把大了。
这里我们使用的是compose操作符

public class Transformer {

    /**
     * @param <T> 泛型
     * @return 返回Observable
     */
    public static <T> ObservableTransformer<T, T> switchSchedulers() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
                return upstream
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .doOnSubscribe(new Consumer<Disposable>() {
                            @Override
                            public void accept(@NonNull Disposable disposable) throws Exception {

                            }
                        })
                        .subscribeOn(AndroidSchedulers.mainThread())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}

        //封装之后具体是这样的使用的
        retrofit
                  .......省略部分代码
                  .compose(Transformer.<Top250Bean>switchSchedulers())
4、对Observer的封装
        //原始请求Observer的结果是这样的
        new Observer<Top250Bean>() {
                            @Override
                            public void onSubscribe(@NonNull Disposable d) {

                            }

                            @Override
                            public void onNext(@NonNull Top250Bean top250Bean) {
                                      //请求成功
                            }

                            @Override
                            public void onError(@NonNull Throwable e) {
                                      //请求失败
                            }

                            @Override
                            public void onComplete() {

                            }
                        }

接下来我们对其进行封装,建一个BaseObserver类,继承Observer和ISubscriber,其中ISubscriber是我们提供的一个接口

public interface ISubscriber<T extends BaseResponse> {

    void doOnSubscribe(Disposable d);

    void doOnError(String errorMsg);

    void doOnNext(T t);

    void doOnCompleted();
}

其中我们定义了一个泛型T继承BaseResponse,也许这里你会有疑问,问什么要继承BaseResponse,因为部分请求结果格式都是以下格式

code为错误状态码 ; msg为错误描述信息
        
        {
        code: 0/400/401...,
        msg: 错误描述...,
        ...

        }

这样的格式便于我们对数据统一处理,比如后台规定code=200是请求成功并返回数据,否则就返回msg显示相关错误信息,code=400强制下线,等等自己的一套code规定,遇到这样的我们可以这样在底层统一处理

    @Override
    public void onNext(@NonNull T t) {
        if(t.getCode==200){
               doOnNext(t);
        }else if (t.getCode==400){
            //处理单设备登陆下线的逻辑
        }else{
         showToast(t.getMsg());
        }
       
    }

来看下完整的BaseObserver代码

public abstract class BaseObserver<T extends BaseResponse> implements Observer<T>, ISubscriber<T> {

    private Toast mToast;

    protected void doOnNetError() {
    }

    @Override
    public void onSubscribe(@NonNull Disposable d) {
        doOnSubscribe(d);
    }

    @Override
    public void onNext(@NonNull T t) {
        //这部分因为不同的后台处理逻辑不一样就没直接处理
        //使用者可以根据自己的需求进行定制即可
        doOnNext(t);
    }

    @Override
    public void onError(@NonNull Throwable e) {
        if (e instanceof SocketTimeoutException) {
            setError(ApiException.errorMsg_SocketTimeoutException);
        } else if (e instanceof ConnectException) {
            setError(ApiException.errorMsg_ConnectException);
        } else if (e instanceof UnknownHostException) {
            setError(ApiException.errorMsg_UnknownHostException);
        } else {

            String error = e.getMessage();
            showToast(error);
            doOnError(error);
        }
    }


    @Override
    public void onComplete() {
        doOnCompleted();
    }


    private void setError(String errorMsg) {
        showToast(errorMsg);
        doOnError(errorMsg);
        doOnNetError();
    }


    /**
     * Toast提示
     *
     * @param msg 提示内容
     */
    protected void showToast(String msg) {
        if (mToast == null) {
            mToast = Toast.makeText(BaseRxHttpApplication.getContext(), msg, Toast.LENGTH_SHORT);
        } else {
            mToast.setText(msg);
        }
        mToast.show();
    }

}

如果你不想这个方法返回时候那么多方法,就可以在继承BaseObserver写个CommonObserver做二次处理即可,github代码中已经封装了一个,有需求的可以看下,至此简单的模块封装已经完成了,各个类写好之后需要一个入口去提供方法供外部调用,我们建一个RxHttpUtils类,里边会暴露很多方法,去设置不同参数,前边我们封装的RetrofitClient和HttpClient我们都可以在拿到builder之后进行参数处理了,因为都是些对方法的封装,就不在此贴代码了,需要的可以去看看RxHttpUtils 2.x

5、由于篇幅有限在此对文件下载的进度回调的封装就不做过多说明了,想了解的移步至源码去看看哈

最后来看看我们封装之后的效果吧

                RxHttpUtils
                        .createApi(ApiService.class)
                        .getBook()
                        .compose(Transformer.<BookBean>switchSchedulers(loading_dialog))
                        .subscribe(new CommonObserver<BookBean>(loading_dialog) {
                            @Override
                            protected void getDisposable(Disposable d) {
                                  //用于在onDestroy的时候取消订阅使用
                            }

                            @Override
                            protected void onError(String errorMsg) {
                            }

                            @Override
                            protected void onSuccess(BookBean bookBean) {

                            }
                        });

是不是代码减少很多,看起来更加清爽了

解答疑惑

相信到这里部分人还会有疑惑,为什么不把ApiService和compose也封装进去呐,毕竟网速也有那样去做的,我这里不想对使用者做太多干涉,让使用者自己去创建自己的ApiService,里边的方法名之类的都可以根据自己公司的命名规范去处理,另外使用compose操作符我们可以传一些参数请求的时候显示loading之类的,我代码中已经处理了

以上内容只是对封装的RxHttpUtils 2.x内部实现做了简单的介绍,也有很多功能点没有介绍到位,建议读者结合(RxHttpUtils 2.x)使用说明去进一步了解


系列文章

RXjava+Retrofit 史上最精简封装(RxHttpUtils 1.x)使用说明

RxJava+Retrofit 史上最精简封装(RxHttpUtils 2.x)使用说明

上一篇下一篇

猜你喜欢

热点阅读