简单实现RxJava2+Okhttp+Retrofit2的网络请求框架封装

简单实现RxJava2+Okhttp+Retrofit2的网络请求框架封装

本人近期在看网络请求框架封装时,看到网上呼声最高的是此类,轻便又简洁,近日闲来无事,就为各位农友写了个案例,抠脚来的不喜勿喷哦。

  • 简单实现RxJava2OkhttpRetrofit2的网络请求框架封装
    • OKhttp
    • RxJava2
    • Retrofit

  • Retrofit2的配置以及使用
  • Okhttp的配置以及使用
  • RxJava2的配置以及使用
  • 对回掉的简单封装

这里写图片描述

OKhttp

OKhttp 相信各位农友都比较熟悉,它是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势 Okhttp官网

  • Okhttp的配置

    这里我是使用的gson作为ConverterFactory,你也可以使用其他的,并且自己写一个类实现下factory,我并没有这样操作。在这里提醒下,有些后台返回的数据格式并不是json格式,而是string格式,这里我介绍下对string格式返回值的支持 scalars,下面会见到配置
    
     //okhttp的包
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    //retrofit对gson的支持
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    //请求字符串
    compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
  • Okhttp的使用
创建一个对网络的管理类HttpManager,里面可以封装网络请求的baseurl,以及对okhttp的初始化
    不同需求的okhttpclient可以多封装几个方法('详细代码后面会贴出')

    'private OkHttpClient.Builder initOkhttpClien(){
        //日志显示级别
        OkHttpClient.Builder httpclient=new OkHttpClient().newBuilder();
        httpclient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        //添加 token 过期拦截,和日志打印,这里我写了个拦截器,这里可以对token刷新进行一些操作,具体看业务需要
        httpclient.addInterceptor(new TokenInterceptor());
        return httpclient;
    }'

详细的okhttp使用以及源码讲解可以跳转Okhttp详解

这里写图片描述

RxJava2

ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。实时数据处理是一件普通的现象,有一个高效、干净和可扩展的方式来处理这些情景是重要的。使用 Observables 和 Operators 来熟练操作它们。ReactiveX 提供一个可组合又灵活的 API 来创建和处理数据流,同时简化了异步编程带来的一些担忧,如:线程创建和并发问题。
简单点来说:就是一个观察者通过订阅被观察者,依据被观察者的一些变化做出相应的动作,观察者可以改变被观察者的生活状态
- RxJava2的配置

    这里我使用的是rxjava2,所以导入的包也是对应rxjava2的
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    适配器 在前面加了,这里就不重复了
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
  • RxJava2的使用
这里我写一个简单的例子:有三个学生,他们每个人有多种课程,我想打印每一个人的课程名都有哪些
    **这里是为了演示使用,例子并没有实际意义**
 public void testRx(){
        List list=new ArrayList<>();
        Student student=new Student();
        List scos=new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Scort sc=new Scort();
            sc.setName("name1"+i);
            scos.add(sc);
        }
        student.setName("zhs1");
        student.setScorts(scos);

        Student student2=new Student();
        List scos2=new ArrayList<>();
        for (int j = 0; j < 5; j++) {
            Scort sc=new Scort();
            sc.setName("name2"+j);
            scos2.add(sc);
        }
        student2.setName("zhs2");
        student2.setScorts(scos2);

        Student student3=new Student();
        List scos3=new ArrayList<>();
        for (int h = 0; h < 5; h++) {
            Scort sc=new Scort();
            sc.setName("name"+h);
            scos3.add(sc);
        }
        student3.setName("zhs3");
        student3.setScorts(scos3);

        list.add(student);
        list.add(student2);
        list.add(student3);
        Consumer与1.0的与Action1类似
        Consumer consumer=new Consumer() {
            @Override
            public void accept(Scort scort) throws Exception {
                System.out.println("课程名      "+scort.getName());
            }
        };
        //背压的封装,具体可以看2.0介绍
        //不需要for循环get等一堆操作既可以打印,简介明了
        Flowable.fromIterable(list).flatMap(new Function>() {
            @Override
            public Publisher apply(Student student) throws Exception {
                return Flowable.fromIterable(student.getScorts());
            }
        }).subscribe(consumer);
    }

代码中Rxjava的体现在于 BaseObserver以及RxSchedulers
后面会见到他们的使用

一个是对Observer的封装,一个是对全局的请求拦截的配置;
如果你不知道Observer是干什么的,建议去看看Rxjava的介绍
public abstract class BaseObserver<T> implements Observer<BaseBean<T>> {
    private Context mContext;
    private ProgressDialog progressDialog;
    private Disposable disposable;

    //默认无效果的请求
    protected BaseObserver(Context context){
        this.mContext=context.getApplicationContext();
    }

    //带进度条的请求
    protected BaseObserver(Context context,boolean showProgress){
        this.mContext=context.getApplicationContext();
        if(showProgress){
            progressDialog=new ProgressDialog(context);
            progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialogInterface) {
                    disposable.dispose();
                }
            });
        }
    }

    @Override
    public void onSubscribe(Disposable d) {
        disposable=d;
    }

    @Override
    public void onNext(BaseBean value) {
        //这里对数据bean的封装,这里看个人的网络回掉的结果来操作,我是随便写的
        if (value.getTotal()>0) {
            T t = value.getSubject();
            onHandleSuccess(t);
        } else {
            onHandleError(value.getTitle());
        }

    }

    @Override
    public void onError(Throwable e) {
        if(progressDialog!=null){
            progressDialog.dismiss();
        }
    }

    @Override
    public void onComplete() {
        if(progressDialog!=null&&progressDialog.isShowing()){
            progressDialog.dismiss();
        }
    }

    protected abstract void onHandleSuccess(T t);

    protected void onHandleError(String msg) {
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
    }
}
/**
 * 设置同一的拦截,对每个订阅做相同的标准
 */
public class RxSchedulers {
    public static <T> ObservableTransformer<T, T> compose(final Context context) {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(Observable observable) {
                return observable
                        .subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .doOnSubscribe(new Consumer() {
                            @Override
                            public void accept(Disposable disposable) throws Exception {
                                if(!NetUtils.isNetworkConnected(context)){
                                    Toast.makeText(context,"网络异常",Toast.LENGTH_SHORT).show();
                                }
                            }
                        })
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}
也可以换一种写法(看个人喜好)
public class  BaseObservableTransFormer<T> implements ObservableTransformer<T,T>{
    private Context context;
    public BaseObservableTransFormer(Context context){
        this.context=context;
    }
    @Override
    public ObservableSource<T> apply(Observable upstream) {
        return upstream.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        //判断网络
                        if(!NetUtils.isNetworkConnected(context)){
                            Toast.makeText(context,"网络异常",Toast.LENGTH_SHORT).show();
                        }
                    }
                })
                .observeOn(AndroidSchedulers.mainThread());
    }
}

推荐一个Rxjava的入门简介Rxjava简介

这里写图片描述

Retrofit

简单的说Retrofit将访问方式分成了三步,1.request的type设置;2.参数的配置,3.对response的回掉处理;
其实volley也是这样,只不过retrofit将更多的事情放到了对callback的处理,所以让他做到了像一个方法请求了api似S的效果;

  • Retrofit的配置

    这里我使用的是rxjava2,所以导入的包也是对应rxjava2的,如果你还是使用rxjava1,可以设置rxjava1的包,此包对1也兼容
    
    //retrofit的包
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    //对gson的支持
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    //对rxjava的适配
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
  • Retrofit的使用
1.创建一个请求的接口类
    //此处封装的是Observable,Rxjava中的被观察者
public interface ApiRequest {
    @GET("top250")
    Observable>> getMovie(@Query("start") int start, @Query("count") int count);
    //这个BaseBean是我对数据的封装,像后台返回给我们的数据都是具有一定的格式,我们以此可以做一些操作
    ...类似更多的接口都卸载这个类中
}
2.配置Retrofit的全局使用
        //同样,我们在配置okhttp的HttpManager类中初始化这个配置,这里使用简单的单例模式
        SingleHolder写在HttpManager类中
        private static class SingleHolder{
        private static  HttpManager httpManager=null;
        public static HttpManager getInstance(Context context){
            if(httpManager==null){
                httpManager=new HttpManager(context);

            }
            return httpManager;
        }
    }
    //对Retrofit的初始化
    private HttpManager(Context context){
        this.mContext=context;
        retrofit=new Retrofit.Builder()
                //对okgttp的初始化
                .client(initOkhttpClien().build())
                //基础的网络请求域名
                .baseUrl(baseUrl)
                //对返回字符串的支持,注意这个要写在gson之前
                .addConverterFactory(ScalarsConverterFactory.create())
                //对gson的支持
                .addConverterFactory( GsonConverterFactory.create())
                //对rxjava的支持
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        //接口方法类的反射获取
        request = retrofit.create(ApiRequest.class);
    }
    //简单的单例模式
    public static HttpManager init(Context context){
        return SingleHolder.getInstance(context);
    }
3.使用rxjava来返回响应体
    //这个方法也是写在HttpManager中,对应的在ApiRequest 写一个方法,这里就写一个
    public void getMovie(int strat, int count, BaseObserver> subscriber){
        request.getMovie(strat,count).compose(RxSchedulers.>>compose(mContext)).subscribe( subscriber);
    }

4.在代码中的使用
 HttpManager.init(this).getMovie(0, 10, new BaseObserver>(this) {
        //对网络判断的封装放在RxSchedulers中,对返回值code判断放在BaseObserver中
            @Override
            protected void onHandleSuccess(List subjects) {
                System.out.println(subjects.get(2).toString());
            }
        });

项目地址 https://gitee.com/nimodou/RetrofitRxjava.git


你可能感兴趣的:(Rxjava2)