Android开发中RxJava处理的四种场景+实战学习

147 阅读4分钟

场景一: 单请求异步处理

由于在Android UI线程中不能做一些耗时操作,比如网络请求,大文件保存等,所以在开发中经常会碰到异步处理的情况,我们最典型的使用场景是RxJava+Retrofit处理网络请求

MyService myService = retrofit.create(MyService.class);
myService.getSomething()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::updateUI, this::showError);

为了使代码看起来简洁点,这边还使用了lambda表达式, updateUI 和 showError 需要在当前类中实现,比如:

public void updateUI(Data data){
      //TODO something
}
​
public void showError(throwable t){
      //show error msg
}

场景二: 多异步请求连续调用

这种场景其实也很常见,我们做用户头像编辑的使用,一般就会有三个请求需要连续调用:

  1. 请求头像上传的地址
  2. 上传头像
  3. 更新用户信息

在平时的代码里,我们需要一步步callback嵌套下来,代码冗长太难看,而且不好维护,使用RxJava链式调用处理代码逻辑就会非常清晰

Observable.just(1)
  .map(this::task1)
  .map(this::task2)
  .map(this::task3)
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(this::updateUI, this::showError);

这里的just发送的固定值1,没有实际意义,只是我觉得这样更信息

你也可以用Observable.create创建observable。

场景三: 多异步请求合并处理

有时候在项目中,我们会碰到组合多个请求的结果后,再更新UI的情况,比如我们项目中就有一个从多个请求地址获取通知数据,然后在APP上再按时间顺序组合后展示的需求,这时候我们就可以用RxJava的zip函数来处理了

MyService myService = retrofit.create(MyService.class);
Observable o1 = myService.getNotification1();
Observable o2 = myService.getNotification2();
Observable.zip(o1,o2, this::combiNotification)
             .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::updateUI, this::showError);
​
​
public List<Notification> combiNotification(List<Notification> n1, List<Notification> n2){
      //TODO 合并通知列表
}

zip函数会等待两个请求都完成后,调用我们的合并方法combiNotification,等合并处理后再回调subscribe中的方法。

场景四: 定时轮询

RxJava还特别适合对定时轮询任务的处理, 一种典型的例子就是APP提交了一个任务给后台异步处理,假设后台处理需要1-2分钟左右,我们需要定时到后台查询进度,并更新到UI上, 传统的做法是用Handler的postDelay方法,用RxJava实现的话就会非常简洁

Subscription subscription =  Observable.interval(2, TimeUnit.SECONDS)
                .map(this::getProgress)
                .takeUntil(progress -> progress !=  100)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Long>() {
                    @Override
                    public void onCompleted() {
                        //TODO finished
                    }
​
                    @Override
                    public void onError(Throwable e) {
                    }
​
                    @Override
                    public void onNext(int progress) {
                         //TODO update progress
                    }
                });

我们以定时2秒查询一次,直到进度progress=100为止,自动终止轮询。

定时心跳

场景描述:

  1. 一个发送数据出口
  2. 定时循环发送一个数据
  3. 当需要发送一个数据临时插入一个数据从出口发送

需要用到的操作符

repat 重复发送 delay 延时发送 just 快速创建被观察者,插入心跳数据 mergeDelayError 合并发送,错误延时

流程

主要是创建两个被观察者,一个负责心跳的发送,另外一个负责数据的发送

实现代码

重复执行某个动作直到成功,或失败,或超时

场景描述:

  1. 重复执行某个动作
  2. 成功后中断继续执行操作
  3. 错误继续执行
  4. 未响应发出超时错误,并继续执行
  5. 达到超时次数,中止执行

需要用到的操作符

distinct 过滤 timeout 超时发出错误 retryWhen 错误重试 zipWith 合并(用于统计错误重试次数) delay 延时(用于发送错误后等待一段时间继续发送)

流程

发出动作请求,等待结果,过滤结果。

  1. 结果为onError立马重新发出动作请求
  2. 等待指定时间没有结果,发出超时onError然后重新发出动作请求
  3. 结果为成功结果终止动作请求
  4. 直到成功为止,或者超过重试的指定次数

实现代码

任务流(循环)

场景描述

  1. 一个动作完成后才执行下一个动作
  2. 所有动作完成后重复继续执行

需要用到的操作符

concat 连接操作符(只能连接9个,但是可以嵌套) repat 循环

流程

使用flatmap创建一个基本异步任务,用concat实现连接,用reapt实现循环

实现代码

image.png

以上各种RxJava方法都是异步耗时调用,考虑到Activity的退出时请求还没有完成,我们需要在Activity的OnDestroy方法中取消RxJava调用,以及一个实战步骤。更多有关RxJava的学习或Android核心技术的进阶 可以> 前往

传送直达↓↓↓ :link.juejin.cn/?target=htt…

文末

rx的优势:

  • 线程切换,不需要像handler那样 请求与结果在不同地方
  • 链式编程, 复杂的逻辑形成一条链,消灭回调地狱、迷之缩进,并且可以在期间做各种线程切换

后面所有的线程切换都是用封装好的方法