RxRetrofit-终极封装-深刻浅出&网络请求

背景:

CSDN博客发布了一系列的RxJava+Retrofit+OkHttp深刻浅出-终极封装是否是很眼熟,是的仍是它,不过是不一样的配方。以前发出后收到不少朋友的关注,本来只是本身学习后的一些经验总结,可是有同窗运用到实战当中,这让我很惶恐,全部后续一直更新了不少次版本,有些地方不免有所变更致使以前的博客有所出入,正好最近受到掘金邀请内测博客,因此决定从新写一版,按照最后迭代完成的封装详细的讲述一遍,欢迎你们关注!html

注意:因为本章的特殊性,后续文章比较长并且复杂,涉及内容也不少,因此你们准备好茶水,前方高能预警。java

RxJava+Retrofit+OkHttp深刻浅出-终极封装android


封装成果

封装完之后,具备以下功能:git

1.Retrofit+Rxjava+okhttp基本使用方法
    2.统一处理请求数据格式
    3.统一的ProgressDialog和回调Subscriber处理
    4.取消http请求
    5.预处理http请求
    6.返回数据的统一判断
    7.失败后的retry封装处理
    8.RxLifecycle管理生命周期,防止泄露复制代码

实现效果:


具体使用

封装后http请求代码以下github

// 完美封装简化版
    private void simpleDo() {
        SubjectPost postEntity = new SubjectPost(simpleOnNextListener,this);
        postEntity.setAll(true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

    // 回调一一对应
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() {
        @Override
        public void onNext(List<Subject> subjects) {
            tvMsg.setText("已封装:\n" + subjects.toString());
        }

        /*用户主动调用,默认是不须要覆写该方法*/
        @Override
        public void onError(Throwable e) {
            super.onError(e);
            tvMsg.setText("失败:\n" + e.toString());
        }
    };复制代码

是否是很简单?你可能说这还简单,好我们对比一下正常使用Retrofit的方法数据库

/** * Retrofit加入rxjava实现http请求 */  
   private void onButton9Click() {  
       //手动建立一个OkHttpClient并设置超时时间 
       okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder();  
       builder.connectTimeout(5, TimeUnit.SECONDS);  

       Retrofit retrofit = new Retrofit.Builder()  
               .client(builder.build())  
               .addConverterFactory(GsonConverterFactory.create())  
               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())  
               .baseUrl(HttpManager.BASE_URL)  
               .build();  

/        加载框  
       final ProgressDialog pd = new ProgressDialog(this);  

       HttpService apiService = retrofit.create(HttpService.class);  
       Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);  
       observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())  
               .subscribe(  
                       new Subscriber<RetrofitEntity>() {  
                           @Override  
                           public void onCompleted() {  
                               if (pd != null && pd.isShowing()) {  
                                   pd.dismiss();  
                               }  
                           }  

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

                           @Override  
                           public void onNext(RetrofitEntity retrofitEntity) {  
                               tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString());  
                           }  

                           @Override  
                           public void onStart() {  
                               super.onStart();  
                               pd.show();  
                           }  
                       }  

               );  
   }复制代码

可能你发现确是代码有点多,可是更加可怕的是,若是你一个activity或者fragment中屡次须要http请求,你须要屡次重复的写回调处理(一个回到就有4个方法呀!!!!反正我是忍受不了),并且以上处理尚未作过多的判断和错误校验就如此复杂!~好了介绍完了,开始我们的优化之路吧!json


项目结构:


RxJava

若是你对RxJava不了解,好吧骚年赶快学学吧,否则真会out了,下面给出博主当初学习RxJava的一些资源:api


Retrofit

咱家今天的主角来了,我们也深刻浅出一下了解下Retrofit使用,前方高能,若是你是深度Retrofit选手请直接跳过本节!!!缓存

1.首先确保在AndroidManifest.xml中请求了网络权限

<uses-permission android:name="android.permission.INTERNET"/>复制代码

2.在app/build.gradle添加引用

/*rx-android-java*/
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.trello:rxlifecycle:1.0'
    compile 'com.trello:rxlifecycle-components:1.0'
    /*rotrofit*/
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0'
    compile 'com.google.code.gson:gson:2.8.0'复制代码

3.经常使用注解

这里介绍一些经常使用的注解的使用服务器

  • @Query@QueryMap:用于Http Get请求传递参数

  • @Field:用于Post方式传递参数,须要在请求接口方法上添加@FormUrlEncoded,即以表单的方式传递参数

  • @Body:用于Post,根据转换方式将实例对象转化为对应字符串传递参数.好比Retrofit添加GsonConverterFactory则是将body转化为gson字符串进行传递

  • @Path:用于URL上占位符

  • @Part:配合@Multipart使用,通常用于文件上传

  • @Header:添加http header

  • @Headers:跟@Header做用同样,只是使用方式不同,@Header是做为请求方法的参数传入,@Headers是以固定方式直接添加到请求方法上

ReTrofit基本使用:

首先给定一个测试接口文档,后面的博客中咱们都是用这个接口调试

/** * @api videoLink 50音图视频连接 * @url http://www.izaodao.com/Api/AppFiftyToneGraph/videoLink * @method post * @param once_no bool(选填,ture无连接) 一次性获取下载地址 * @return json array( * ret:1成功,2失败 * msg:信息 * data:{ * name:视频名称 * title:标题 * } )复制代码

1.初始化retrofit

要向一个api发送咱们的网络请求 ,咱们须要使用Retrofit builder类并指定servicebase URL(一般状况下就是域名)。

String BASE_URL = " http://www.izaodao.com/Api/"  
    Retrofit retrofit = new Retrofit.Builder()  
            .baseUrl(BASE_URL)  
            .addConverterFactory(GsonConverterFactory.create())  
            .build();复制代码

2.设置接口service

注意到每一个endpoint 都指定了一个关于HTTP(GET, POST, 等等。) 方法的注解以及用于分发网络调用的方法。并且这些方法的参数也能够有特殊的注解。

/** * 接口地址 * Created by WZG on 2016/7/16. */  
public interface MyApiEndpointInterface {  
    @POST("AppFiftyToneGraph/videoLink")  
    Call<RetrofitEntity> getAllVedio(@Body boolean once_no) }复制代码

3.获得call而后同步处理处理回调:

MyApiEndpointInterface apiService = retrofit.create(MyApiEndpointInterface.class);  
Call<RetrofitEntity> call = apiService.getAllVedio(true);  
call.enqueue(new Callback<RetrofitEntity>() {  
    @Override  
    public void onResponse(Response<RetrofitEntity> response, Retrofit retrofit) {  
        RetrofitEntity entity = response.body();  
        Log.i("tag", "onResponse----->" + entity.getMsg());  
    }  

    @Override  
    public void onFailure(Throwable t) {  
        Log.i("tag", "onFailure----->" + t.toString());  

    }  
});复制代码

这就是简单的Retrofit使用步骤,接下来咱们结合RxJava讲述

ReTrofit+Rxjava基本使用

对比以前的Retrofit使用

1.在于咱们须要修改service接口返回信息咱们须要返回一个Observable对象

@POST("AppFiftyToneGraph/videoLink")  
Observable<RetrofitEntity> getAllVedioBy(@Body boolean once_no);复制代码

2.而后初始化Retrofit须要添加对Rxjava的适配,注意必定要retrofit2才有这个功能哦

Retrofit retrofit = new Retrofit.Builder()  
                .client(builder.build())  
                .addConverterFactory(GsonConverterFactory.create())  
               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())  
                .baseUrl(HttpManager.BASE_URL)  
                .build();复制代码

3.回调经过RxJava处理

HttpService apiService = retrofit.create(HttpService.class);  
       Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true);  
       observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())  
               .subscribe(  
                       new Subscriber<RetrofitEntity>() {  
                           @Override  
                           public void onCompleted() {  
                           }  

                           @Override  
                           public void onError(Throwable e) {                                
                           }  

                           @Override  
                           public void onNext(RetrofitEntity retrofitEntity) {  
                               tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString());  
                           }                            
                       }  

               );复制代码

简单的RxJava集合Retrofit的使用就介绍完了,一样的能够发现使用起来不少重复性的代码,并且使用也不是那么简单,因此才有了下面的封装


ReTrofit+Rxjava进阶封装之路

先来一张流程图压压惊


请求数据封装

1.参数

首先须要封装的使咱们的数据类,在数据类中须要封装请求中用到的相关数据的设置,好比请求参数、方法、加载框显示设置等等

public abstract class BaseApi<T> implements Func1<BaseResultEntity<T>, T> {
    //rx生命周期管理
    private SoftReference<RxAppCompatActivity> rxAppCompatActivity;
    /*回调*/
    private SoftReference<HttpOnNextListener> listener;
    /*是否能取消加载框*/
    private boolean cancel;
    /*是否显示加载框*/
    private boolean showProgress;
    /*是否须要缓存处理*/
    private boolean cache;
    /*基础url*/
    private  String baseUrl="http://www.izaodao.com/Api/";
    /*方法-若是须要缓存必须设置这个参数;不须要不用設置*/
    private String mothed;
    /*超时时间-默认6秒*/
    private int connectionTime = 6;
    /*有网状况下的本地缓存时间默认60秒*/
    private int cookieNetWorkTime=60;
    /*无网络的状况下本地缓存时间默认30天*/
    private int cookieNoNetWorkTime=24*60*60*30;
}复制代码

注释很详细,这里不具体描述了,因为这里是最后封装完成之后的代码,因此有些内容本章还会部分不会涉及,由于功能太多,仍是按照一开始的博客章节讲解。

2.抽象api接口

/** * 设置参数 * * @param retrofit * @return */
    public abstract Observable getObservable(Retrofit retrofit);复制代码

经过子类也便是咱们的具体api接口,经过getObservable实现service中定义的接口方法,例如:

public class SubjectPostApi extends BaseApi {
     xxxxxxx
     xxxxxxx

 @Override
    public Observable getObservable(Retrofit retrofit) {
        HttpPostService service = retrofit.create(HttpPostService.class);
        return service.getAllVedioBys(isAll());
    }
}复制代码

经过传入的Retrofit对象,能够随意切换挑选Service对象,获得定义的注解方法,初始完成之后返回Observable对象。

3.结果判断

这里结合RxJavamap方法在服务器返回数据中,统一处理数据处理,因此BaseApi<T> implements Func1<BaseResultEntity<T>, T>,后边结合结果处理连接起来使用

@Override
    public T call(BaseResultEntity<T> httpResult) {
        if (httpResult.getRet() == 0) {
            throw new HttpTimeException(httpResult.getMsg());
        }
        return httpResult.getData();
    }复制代码

因为测试接口,也是当前咱们公司接口都是有统一规则的,想必你们都有这样的接口规则,因此才有这里的统一判断,规则以下:

* ret:1成功,2失败  
 * msg:信息  
 * data:{  
 *       name:视频名称  
 *       title:标题  
 * }复制代码

其实上面的接口文档中就介绍了,统一先经过ret判断,失败显示msg信息,data是成功后的数据也就是用户关心的数据,因此可封装一个结果对象BaseResultEntity.

4.结果数据

/** * 回调信息统一封装类 * Created by WZG on 2016/7/16. */
public class BaseResultEntity<T> {
    // 判断标示
    private int ret;
    // 提示信息
    private String msg;
    //显示数据(用户须要关心的数据)
    private T data;


    xxxxx  get-set  xxxxx
}复制代码

这里结合BaseApiFunc1判断,失败直接抛出一个异常,交个RxJavaonError处理,成功则将用户关心的数据传给Gson解析返回

5.泛型传递

BaseResultEntity<T>中的泛型T也就是咱们所关心的回调数据,一样也是Gson最后解析返回的数据,传递的过程根节点是经过定义service方法是给定的,例如:

public interface HttpPostService {
    @POST("AppFiftyToneGraph/videoLink")
    Call<RetrofitEntity> getAllVedio(@Body boolean once_no);
}复制代码

其中的RetrofitEntity就是用户关心的数据类,经过泛型传递给最后的接口。

6.强调

不少兄弟经过QQ群反馈给我说,使用一个接口须要写一个对应的api类继承BaseApi是否是很麻烦,我这里强调一下,这样封装是为了将一个Api接口做为一个对象去封装,我的以为有必要封装成一个类,在往后工程日益增长接口随着增长的同时,对象的作法更加有利于查找接口和修改接口有利于迭代。


操做类封装

1初始对象

首先初始化一个单利方便HttpManager请求;这里用了volatile的对象,不懂的同窗能够参考个人另外一篇博客

你真的会写单例吗

private volatile static HttpManager INSTANCE;

    //构造方法私有
    private HttpManager() {
    }

    //获取单例
    public static HttpManager getInstance() {
        if (INSTANCE == null) {
            synchronized (HttpManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new HttpManager();
                }
            }
        }
        return INSTANCE;
    }复制代码

2接口处理和回调处理:

/** * 处理http请求 * * @param basePar 封装的请求数据 */
    public void doHttpDeal(BaseApi basePar) {
        //手动建立一个OkHttpClient并设置超时时间缓存等设置
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(basePar.getConnectionTime(), TimeUnit.SECONDS);
        builder.addInterceptor(new CookieInterceptor(basePar.isCache()));

        /*建立retrofit对象*/
        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(basePar.getBaseUrl())
                .build();


        /*rx处理*/
        ProgressSubscriber subscriber = new ProgressSubscriber(basePar);
        Observable observable = basePar.getObservable(retrofit)
                /*失败后的retry配置*/
                .retryWhen(new RetryWhenNetworkException())
                /*生命周期管理*/
                .compose(basePar.getRxAppCompatActivity().bindToLifecycle())
                /*http请求线程*/
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                /*回调线程*/
                .observeOn(AndroidSchedulers.mainThread())
                /*结果判断*/
                .map(basePar);

        /*数据回调*/
        observable.subscribe(subscriber);
    }复制代码

首先经过api接口类BaseApi的实现类中数据初始化OkHttpClientRetrofit对象,其中包含了url,超时等,接着经过BaseApi的抽象方法getObservable获得Observable对象,获得Observable对象之后,咱们就能随意的切换现成来处理,整个请求经过compose设定的rxlifecycle来管理生命周期,因此不会溢出和泄露无需任何担忧,最后再服务器数据返回时,经过map判断结果,剔除错误信息,成功之后返回到自定义的ProgressSubscriber对象中,因此接下来封装ProgressSubscriber对象。


ProgressSubscriber封装

ProgressSubscriber实际上是继承于Subscriber,封装的方法无非是对Subscriber的回调方法的封装

  • onStart():开始
  • onCompleted():结束
  • onError(Throwable e):错误
  • onNext(T t):成功

1.请求加载框

http请求都伴随着加载框的使用,因此这里须要在onStart()使用前初始一个加载框,这里简单的用ProgressDialog代替

/** * 用于在Http请求开始时,自动显示一个ProgressDialog * 在Http请求结束是,关闭ProgressDialog * 调用者本身对请求数据进行处理 * Created by WZG on 2016/7/16. */
public class ProgressSubscriber<T> extends Subscriber<T> {
    /*是否弹框*/
    private boolean showPorgress = true;
    /* 软引用回调接口*/
    private SoftReference<HttpOnNextListener> mSubscriberOnNextListener;
    /*软引用反正内存泄露*/
    private SoftReference<RxAppCompatActivity> mActivity;
    /*加载框可本身定义*/
    private ProgressDialog pd;
    /*请求数据*/
    private BaseApi api;


    /** * 构造 * * @param api */
    public ProgressSubscriber(BaseApi api) {
        this.api = api;
        this.mSubscriberOnNextListener = api.getListener();
        this.mActivity = new SoftReference<>(api.getRxAppCompatActivity());
        setShowPorgress(api.isShowProgress());
        if (api.isShowProgress()) {
            initProgressDialog(api.isCancel());
        }
    }


    /** * 初始化加载框 */
    private void initProgressDialog(boolean cancel) {
        Context context = mActivity.get();
        if (pd == null && context != null) {
            pd = new ProgressDialog(context);
            pd.setCancelable(cancel);
            if (cancel) {
                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        onCancelProgress();
                    }
                });
            }
        }
    }


    /** * 显示加载框 */
    private void showProgressDialog() {
        if (!isShowPorgress()) return;
        Context context = mActivity.get();
        if (pd == null || context == null) return;
        if (!pd.isShowing()) {
            pd.show();
        }
    }


    /** * 隐藏 */
    private void dismissProgressDialog() {
        if (!isShowPorgress()) return;
        if (pd != null && pd.isShowing()) {
            pd.dismiss();
        }
    }
}复制代码

因为progress的特殊性,须要指定content并且不能是Application因此这里传递一个RxAppCompatActivity,而同时上面的HttpManager一样须要,因此这里统一仍是按照BaseApi传递过来,使用软引用的方式避免泄露。剩下的无非是初始化,显示和关闭方法,能够详细看代码。

2.onStart()实现

onStart()中须要调用加载框,而后这里还有网络缓存的逻辑,后面会单独讲解,如今先忽略它的存在。

/** * 订阅开始时调用 * 显示ProgressDialog */
    @Override
    public void onStart() {
        showProgressDialog();
        /*缓存而且有网*/
        if (api.isCache() && AppUtil.isNetworkAvailable(RxRetrofitApp.getApplication())) {
             /*获取缓存数据*/
            CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(api.getUrl());
            if (cookieResulte != null) {
                long time = (System.currentTimeMillis() - cookieResulte.getTime()) / 1000;
                if (time < api.getCookieNetWorkTime()) {
                    if (mSubscriberOnNextListener.get() != null) {
                        mSubscriberOnNextListener.get().onCacheNext(cookieResulte.getResulte());
                    }
                    onCompleted();
                    unsubscribe();
                }
            }
        }
    }复制代码

3.onCompleted()实现

/** * 完成,隐藏ProgressDialog */
    @Override
    public void onCompleted() {
        dismissProgressDialog();
    }复制代码

4.onError(Throwable e)实现

onError(Throwable e)是对错误信息的处理和缓存读取的处理,后续会讲解,先忽略。

/** * 对错误进行统一处理 * 隐藏ProgressDialog * * @param e */
    @Override
    public void onError(Throwable e) {
        dismissProgressDialog();
        /*须要緩存而且本地有缓存才返回*/
        if (api.isCache()) {
            Observable.just(api.getUrl()).subscribe(new Subscriber<String>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    errorDo(e);
                }

                @Override
                public void onNext(String s) {
                    /*获取缓存数据*/
                    CookieResulte cookieResulte = CookieDbUtil.getInstance().queryCookieBy(s);
                    if (cookieResulte == null) {
                        throw new HttpTimeException("网络错误");
                    }
                    long time = (System.currentTimeMillis() - cookieResulte.getTime()) / 1000;
                    if (time < api.getCookieNoNetWorkTime()) {
                        if (mSubscriberOnNextListener.get() != null) {
                            mSubscriberOnNextListener.get().onCacheNext(cookieResulte.getResulte());
                        }
                    } else {
                        CookieDbUtil.getInstance().deleteCookie(cookieResulte);
                        throw new HttpTimeException("网络错误");
                    }
                }
            });
        } else {
            errorDo(e);
        }
    }

    /*错误统一处理*/
    private void errorDo(Throwable e) {
        Context context = mActivity.get();
        if (context == null) return;
        if (e instanceof SocketTimeoutException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else if (e instanceof ConnectException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "错误" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
        if (mSubscriberOnNextListener.get() != null) {
            mSubscriberOnNextListener.get().onError(e);
        }
    }复制代码

5.onNext(T t)实现

/** * 将onNext方法中的返回结果交给Activity或Fragment本身处理 * * @param t 建立Subscriber时的泛型类型 */
    @Override
    public void onNext(T t) {
        if (mSubscriberOnNextListener.get() != null) {
            mSubscriberOnNextListener.get().onNext(t);
        }
    }复制代码

主要是是将获得的结果,经过自定义的接口返回给view界面,其中的软引用对象mSubscriberOnNextListener是自定义的接口回调类HttpOnNextListener.


6.HttpOnNextListener封装

如今只需关心onNext(T t)onError(Throwable e)接口便可,回调的触发点都是在上面的ProgressSubscriber中调用

/** * 成功回调处理 * Created by WZG on 2016/7/16. */
public abstract class HttpOnNextListener<T> {
    /** * 成功后回调方法 * @param t */
    public abstract void onNext(T t);

    /** * 緩存回調結果 * @param string */
    public void onCacheNext(String string){

    }

    /** * 失败或者错误方法 * 主动调用,更加灵活 * @param e */
    public void onError(Throwable e){

    }

    /** * 取消回調 */
    public void onCancel(){

    }
}复制代码

失败后的retry处理

这里你可能会问,Retrofit有自带的retry处理呀,的确Retrofit有自带的retry处理,可是有不少的局限,先看下使用

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.retryOnConnectionFailure(true);复制代码

使用起来仍是很方便,只须要调用一个方法便可,可是它是不可控的,也就是没有办法设置retry时间次数,因此不太灵活,既然如此还不如本身封装一下,由于用RxJava实现这个简直小菜,无形中好像已经给RxJava打了广告,中毒太深。

很简单直接上代码:

/** * retry条件 * Created by WZG on 2016/10/17. */
public class RetryWhenNetworkException implements Func1<Observable<? extends Throwable>, Observable<?>> {
// retry次数
    private int count = 3;
// 延迟
    private long delay = 3000;
// 叠加延迟
    private long increaseDelay = 3000;

    public RetryWhenNetworkException() {

    }

    public RetryWhenNetworkException(int count, long delay) {
        this.count = count;
        this.delay = delay;
    }

    public RetryWhenNetworkException(int count, long delay, long increaseDelay) {
        this.count = count;
        this.delay = delay;
        this.increaseDelay = increaseDelay;
    }

    @Override
    public Observable<?> call(Observable<? extends Throwable> observable) {
        return observable
                .zipWith(Observable.range(1, count + 1), new Func2<Throwable, Integer, Wrapper>() {
                    @Override
                    public Wrapper call(Throwable throwable, Integer integer) {
                        return new Wrapper(throwable, integer);
                    }
                }).flatMap(new Func1<Wrapper, Observable<?>>() {
                    @Override
                    public Observable<?> call(Wrapper wrapper) {
                        if ((wrapper.throwable instanceof ConnectException
                                || wrapper.throwable instanceof SocketTimeoutException
                                || wrapper.throwable instanceof TimeoutException)
                                && wrapper.index < count + 1) { //若是超出重试次数也抛出错误,不然默认是会进入onCompleted
                            return Observable.timer(delay + (wrapper.index - 1) * increaseDelay, TimeUnit.MILLISECONDS);

                        }
                        return Observable.error(wrapper.throwable);
                    }
                });
    }

    private class Wrapper {
        private int index;
        private Throwable throwable;

        public Wrapper(Throwable throwable, int index) {
            this.index = index;
            this.throwable = throwable;
        }
    }
}复制代码

使用

到这里,咱们第一步封装已经完成了,下面讲解下如何使用,已经看明白的各位看官,估计早就看明白了使用方式,无非是建立一个api对象继承BaseApi初始接口信息,而后调用HttpManager对象的doHttpDeal(BaseApi basePar)方法,最后静静的等待回调类HttpOnNextListener<T>类返回的onNext(T t)成功数据或者onError(Throwable e)数据。

其实代码就是这样:

api接口对象

/** * 测试数据 * Created by WZG on 2016/7/16. */
public class SubjectPostApi extends BaseApi {
// 接口须要传入的参数 可自定义不一样类型
    private boolean all;
    /*任何你先要传递的参数*/
// String xxxxx;

    /** * 默认初始化须要给定回调和rx周期类 * 能够额外设置请求设置加载框显示,回调等(可扩展) * @param listener * @param rxAppCompatActivity */
    public SubjectPostApi(HttpOnNextListener listener, RxAppCompatActivity rxAppCompatActivity) {
        super(listener,rxAppCompatActivity);
        setShowProgress(true);
        setCancel(true);
        setCache(true);
        setMothed("AppFiftyToneGraph/videoLink");
        setCookieNetWorkTime(60);
        setCookieNoNetWorkTime(24*60*60);
    }

    public boolean isAll() {
        return all;
    }

    public void setAll(boolean all) {
        this.all = all;
    }

    @Override
    public Observable getObservable(Retrofit retrofit) {
        HttpPostService service = retrofit.create(HttpPostService.class);
        return service.getAllVedioBys(isAll());
    }
}复制代码

请求回调

// 完美封装简化版
    private void simpleDo() {
        SubjectPostApi postEntity = new SubjectPostApi(simpleOnNextListener,this);
        postEntity.setAll(true);
        HttpManager manager = HttpManager.getInstance();
        manager.doHttpDeal(postEntity);
    }

    // 回调一一对应
    HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<SubjectResulte>>() {
        @Override
        public void onNext(List<SubjectResulte> subjects) {
            tvMsg.setText("网络返回:\n" + subjects.toString());
        }

        @Override
        public void onCacheNext(String cache) {
            /*缓存回调*/
            Gson gson=new Gson();
            java.lang.reflect.Type type = new TypeToken<BaseResultEntity<List<SubjectResulte>>>() {}.getType();
            BaseResultEntity resultEntity= gson.fromJson(cache, type);
            tvMsg.setText("缓存返回:\n"+resultEntity.getData().toString() );
        }

        /*用户主动调用,默认是不须要覆写该方法*/
        @Override
        public void onError(Throwable e) {
            super.onError(e);
            tvMsg.setText("失败:\n" + e.toString());
        }

        /*用户主动调用,默认是不须要覆写该方法*/
        @Override
        public void onCancel() {
            super.onCancel();
            tvMsg.setText("取消請求");
        }
    };复制代码

后续

到这里,封装功能中不少功能还没涉及和讲解,后续会陆续更新!
先给你们看看为师的彻底体功能:

1.Retrofit+Rxjava+okhttp基本使用方法
    2.统一处理请求数据格式
    3.统一的ProgressDialog和回调Subscriber处理
    4.取消http请求
    5.预处理http请求
    6.返回数据的统一判断
    7.失败后的retry处理
    8.RxLifecycle管理生命周期,防止泄露
    9.文件上传下载(支持多文件,断点续传)
    10.Cache数据持久化和数据库(greenDao)两种缓存机制
    11.异常统一处理复制代码

来个图压压惊:

火烧眉毛的小伙伴能够看这里:

RxJava+Retrofit+OkHttp深刻浅出-终极封装

可是其中有些后续优化迭代未及时更新,别生气,我立刻补!


源码:

RxRetrofit-终极封装-深刻浅出&网络请求-GitHub

其实我还有一个兄弟版本-传送门

我不会告诉你其实我还有个更加简单的版本


建议

若是你对这套封装有任何的问题和建议欢迎加入QQ群告诉我


这篇文章参加掘金技术征文:gold.xitu.io/post/58522d…

相关文章
相关标签/搜索