安卓项目实战之强大的网络请求框架okGo使用详解(五):扩展项目okRx,完美结合RxJava

前言

在第一篇讲解okGo框架添加依赖支持时,还记得我们额外添加的两个依赖吗,一个okRx和一个okServer,这两个均是基于okGo框架的扩展项目,其中okRx可以使请求结合RxJava一起使用,而okServer则提供了强大的下载上传功能,如断点支持,多任务管理等,本篇我们主要讲解okRx的使用。

OkRx主要功能

1,可以很完美结合RxJava做网络请求
2,在使用上比Retrofit更简单方便,门槛更低,灵活性更高
3,网络请求和RxJava调用可以做成一条链试,写法优雅
4,使用Converter接口,支持任意类型的数据自动解析
5,OkRx是扩展的OkGo,所以OkGo包含的所有功能和写法,OkRx全部支持

Rx请求的写法

1,获取Observable对象
我们还是像正常使用OkGo的方式一样,传入我们需要请求的url,和我们需要的参数,写法如下:
在这里插入图片描述这里有两个特殊的方法:

 .converter():该方法参数是网络请求的转换器类实例,功能是将网络请求的结果转换成我们需要的数据类型。
 .adapt():该方法是方法返回值的适配器,功能是将网络请求的Call<T>对象,适配成我们需要的Observable<T>对象。

2. 调用Rx转换代码
在这里插入图片描述上面两步放在一起写,如下:
在这里插入图片描述上面的showLoading和dismissLoading方法是我们在BaseActivity中定义的显示进度和隐藏进度的方法。

private ProgressDialog dialog;

    public void showLoading() {
        if (dialog != null && dialog.isShowing()) return;
        dialog = new ProgressDialog(this);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage("请求网络中...");
        dialog.show();
    }

    public void dismissLoading() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

addDisposable方法是取消请求时使用,见下面取消请求部分讲解。
以上大概就是使用okGo结合RxJava使用的完整案例,其中有两个地方作如下主要说明:

Converter详解

convert接口实现类的作用是用来进行数据转换的,即将网络请求获取到的数据转换成我们泛型指定的对象,作用和retrofit中的gson转换一样,基于此种写法我们就必须额外定义一个继承Convert接口重写convertResponse方法编写解析转换逻辑的实现类,因为.converter()参数为该转换器类的一个实例,就不能像之前只使用okGo那样可以将该部分逻辑直接写进callback实现类中的convertResponse方法之中而不去额外定义转换器类了。

我们知道okGo框架默认提供了三种实现convertResponse转换逻辑的三种convert:

1,StringConverter:按文本解析,解析的编码依据服务端响应头中的Content-Type中的编码格式,自动进行编码转换,确保不出现乱码。
2,BitmapConverter:如果请求的数据是图片,则可以使用该转换器,该方法对图片进行了压缩处理,确保不发生OOM。
3,FileConverter:如果要做文件下载,可以使用该转换器,内部封装了关于文件下载和进度回调的方法。

CallAdapter详解

我们写Rx请求的时候,最后调用了一个adapt()方法,这里面需要一个CallAdapter适配器接口,那么这个适配器是什么东西呢,主要功能就是将我们得到的Call对象,适配成我们需要的Observable对象。
参考okrx2源码的目录结构如下:
在这里插入图片描述在adapter包下,命名规则分为这么几组:
开头的意思:

Observable开头,表示返回的对象是Observable对象
在这里插入图片描述
其他的:
在这里插入图片描述
结尾的意思:
Response结尾,表示返回对象的泛型是Response
在这里插入图片描述
Body结尾,表示返回对象的泛型是T,没有外层的Response包装
在这里插入图片描述
Result结尾,表示返回对象的泛型是Result
在这里插入图片描述

OkRx使用缓存

其实关于adapt()方法还有个重载方法:

adapt(AdapterParam param,callAdapter<T,E> adapter)

可以额外传递一个AdapterParam对象作为第一个参数,我们都知道,okhttp有两种请求方式,一种是同步请求,一种是异步请求,那么这个参数就是控制把当前的Call对象适配成Observable时,是使用同步还是异步的方法,如果不传该参数默认就是使用异步请求,AdapterParam对象只有一个参数,如下:
在这里插入图片描述
如果是使用同步的方法,对应的,我们就使用的是okrx2源码中的CallExecuteObservable对象来适配,如果是异步,那么就使用CallEnqueueObservable对象来适配。他们有什么区别的,其实只有一个最大的区别,就是缓存的使用。
默认情况下,我们使用的是异步请求来适配的,使用方式和okgo使用缓存一样,指定cacheKey和cacheMode就行了,如下:
在这里插入图片描述那么对于okrx缓存回调成功和网络请求回调成功都是回调onNext()方法,那么怎么区分呢,回调的Response对象中有个isFromCache方法,就是表示当前回调是来自缓存还是网络。

注意事项:
1,不同的缓存模式会导致onNext()方法具有不同的回调次数,可能一次或者两次
2, 如果使用同步方法来适配的话,缓存模式CacheMode.FIRST_CACHE_THEN_REQUEST是不生效的,异步才生效,原因是同步请求没法返回两次数据。

取消请求

我们可以在基类BaseActivity中创建这么两个方法,把每一个请求的Disposable对象都交给由统一的CompositeDisposable对象去管理。
在这里插入图片描述在Observer对象的onSubscibe方法中,把Disposable添加到CompositeDisposable中:
在这里插入图片描述然后我们在当前activity界面销毁onDestory方法中或者需要取消的地方调用取消请求的方法:
在这里插入图片描述

rxJava请求之map操作符的使用举例:

map()操作符用于转换一组数据。至于怎么转换,由你自己指定。比如,简单的对数据进行加减乘除处理。又比如,将某一个类转成另一个类。又比如,将一组User类对象(userName是User类的一个字段),转成一组userName对象。

@OnClick(R.id.jsonArrayRequest)
    public void jsonArrayRequest(View view) {
        OkGo.<LzyResponse<List<ServerModel>>>get(Urls.URL_JSONARRAY)//
                .headers("aaa", "111")//
                .params("bbb", "222")//
                .converter(new JsonConvert<LzyResponse<List<ServerModel>>>() {})//
                .adapt(new ObservableBody<LzyResponse<List<ServerModel>>>())//
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {
                        showLoading();
                    }
                })//
                .map(new Function<LzyResponse<List<ServerModel>>, List<ServerModel>>() {
                    @Override
                    public List<ServerModel> apply(@NonNull LzyResponse<List<ServerModel>> response) throws Exception {
                        return response.data;
                    }
                })//
                .observeOn(AndroidSchedulers.mainThread())//
                .subscribe(new Observer<List<ServerModel>>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        addDisposable(d);
                    }

                    @Override
                    public void onNext(@NonNull List<ServerModel> response) {
                        handleResponse(response);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        e.printStackTrace();            //请求失败
                        showToast("请求失败");
                        handleError(null);
                    }

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

Observer与Consumer的区别:他们都是充当观察者角色,后者是简化了前者,减去了许多回调接口。
Consumer是简易版的Observer,他有多重重载,可以自定义你需要处理的信息,我这里调用的是只接受onNext消息的方法,他只提供一个回调接口accept,由于没有onError和onCompete,无法再 接受到onError或者onCompete之后,实现函数回调。无法回调,并不代表不接收,他还是会接收到onCompete和onError之后做出默认操作,也就是监听者(Consumer)不在接收 Observable发送的消息,下方的代码测试了该效果:

        final Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {
                Log.d("MainActivity", Thread.currentThread().getName() + " String:" + s);
            }
        };
 
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> e) throws Exception {
                Log.d("MainActivity", Thread.currentThread().getName() + "emit Hello");
                e.onNext("Hello");
                Log.d("MainActivity", Thread.currentThread().getName() + "emit Complete");
                e.onComplete();
                Log.d("MainActivity", Thread.currentThread().getName() + "emit World");
                e.onNext("World");
            }
        });

参考博客:https://blog.csdn.net/l_o_s/article/details/79409031

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值