java2和,RxJava2的使用与原理浅析(一)

前言

首先,感谢以下作者分享自己对于RxJava的理解

给 Android 开发者的 RxJava 详解

针对RxJava1.×,入门必备

RxJava2 只看这一篇文章就够了 - 掘金

RxJava2的API大全,适合需要使用对应APID时作为资料查看

本文设计源码以及介绍均是基于RxJava2,示例均是为了示例而示例,项目中要使用RxJava,首先在gradle中添加依赖:

implementation 'io.reactivex.rxjava2:rxjava:2.1.4'

implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

一、RxJava2简介

什么是RxJava

A library for composing asynchronous and event-based programs by using observable sequences.

一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库

引用RxJava Github Readme中的介绍,可能看起来仍然让人感到费解,我的理解是:

使用观察者模式,采用链式编程,基于事件的实现异步的库

到这里,没有使用过RxJava的话,一定还是不知道这个库究竟是做什么的,没关系,我们慢慢道来。首先我们需要知道RxJava究竟解决了什么问题。

RxJava解决了什么问题

即使没有使用过,一定也听说过RxJava,RxJava应用如此广泛,那么它究竟解决了什么问题呢?一个词:异步,但是同样是异步,可以使用的工具有很多,我们为什么偏偏要使用RxJava呢?

为什么使用RxJava

我们知道,Android中实现异步的方式有很多,Handler、AsyncTask、runOnUiThread等,为什么我们就要使用RxJava来实现异步呢?换言之,RxJava相比其他实现异步的方法有什么优势呢?最大的优势就是逻辑清晰。

假设有这样一个需求:界面上有一个自定义的视图 imageCollectorView ,它的作用是显示多张图片,并能使用 add(Bitmap) 方法来任意增加显示的图片。现在需要程序将一个给出的目录数组 File[] folders 中每个目录下的 png 图片都加载出来并显示在 imageCollectorView 中。需要注意的是,由于读取图片的这一过程较为耗时,需要放在后台执行,而图片的显示则必须在 UI 线程执行。常用的实现方式有多种,我这里贴出其中一种:

new Thread(() -> {

for (File folder : folders) {

File[] files = folder.listFiles();

for (File file : files) {

if (file.getName().endsWith(".png")) {

final Bitmap bitmap = getBitmapFromFile(file);

runOnUiThread(() -> imageCollectorView.add(bitmap));

}

}

}

}).start();

而如果使用RxJava,实现方式是这样的:

Observable.fromArray(folders)

.flatMap((Function>) folder -> Observable.fromArray(folder.listFiles()))

.filter(file -> file.getName().endsWith("png"))

.map((Function) file -> getBitmapFromFile(file))

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(bitmap -> imageCollectorView.add(bitmap));

一定有人会觉得,这完全没有简洁呀,哪里看出来简洁了,上面所说的简洁只是逻辑简洁,而非代码简洁。

观察一下,你就会发现,使用RxJava,是一条链式调用下来的,完全没有任何嵌套,这种优势在需求变得复杂之后,优势会更加明显,比如我们现在增加一条需求,只需要加载前十张图片,不使用RxJava要怎么去做呢?相信大家都会做,不妨实现去看看,而如果是使用RxJava,修改后的实现如下:

Observable.fromArray(folders)

.flatMap((Function>) folder -> Observable.fromArray(folder.listFiles()))

.filter(file -> file.getName().endsWith("png"))

.map((Function) file -> getBitmapFromFile(file))

.take(LOAD_IMAGE_NUM)

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(bitmap -> imageCollectorView.add(bitmap));

可以看到,仅仅只增加了一行代码,且未新增任何嵌套。

所以RxJava最大的优势就是简洁,无论逻辑如何复杂,总是一条链式调用的简洁。

二、基本使用

在分析RxJava的原理之前,我们首先要了解一下观察者模式,如果已经熟知观察者模式,可以跳过这段。

观察者模式

先让我们想象一下生活中一个场景:

读者(观察者)发现一个微信公众号(被观察者)很不错,希望长期关注,于是便关注(注册)了这个微信公众号,当这个微信公众号发布了一篇新的文章,关注了该微信公众号的读者就会接收到通知(被观察者发送通知给注册了的观察者),如果读者不再关注(注销)该微信公众号,就再不会接收到通知了

以上就是一个典型的观察者模式的流程,生活中像这样的场景还有很多,那么什么是观察者模式呢?

概念

引用《Head First设计模式》一书中的原话

观察者模式定义了对象之间一对多的依赖,这样一来,当该对象改变状态时,它的所有依赖者会受到通知并自动更新

——Head First设计模式

以下是观察者模式UML图

5213fe112fa9

观察者模式UML图

我们可以看到,观察者模式首先定义了两个接口类:Observable(被观察者)、Observer(观察者),

Observable接口中包含三个方法

registerObserver()注册

removeObserver()注销

notifyObservers()发送通知

Observer接口中包含一个方法

update()观察者接收到通知后的行为

以上两个接口,很简单,在这里我就不贴代码了,那么实现类要怎么做呢?

以下是实现类的代码

Observable实现类:

public class ConcreteObservable implements Observable {

private static final String TAG = ConcreteObservable.class.getSimpleName();

List observers;

public ConcreteObservable(){

observers = new ArrayList<>();

}

@Override

public void register(Observer observer) {

if (observer == null) {

throw new NullPointerException("observer cannot be null");

}

if (observers.contains(observer)) {

Log.d("TAG", "you have registered this");

} else {

Log.d("TAG", observer.toString() + " register");

observers.add(observer);

}

}

@Override

public void removeObserver(Observer observer) {

if (observer == null) {

throw new NullPointerException("observer cannot be null");

}

if (observers.contains(observer)) {

Log.d("TAG", observer.toString() + " remove");

observers.remove(observer);

} else {

Log.d("TAG", "you have not registered this");

}

}

@Override

public void notifyObservers() {

for (Observer observer : observers) {

observer.update();

}

}

Observer实现类:

public class TomObserver implements Observer {

private static final String TAG = TomObserver.class.getSimpleName();

@Override

public void update() {

Log.d("TAG", "notify Tom");

}

@Override

public String toString() {

return "Tom";

}

}

public class KittyObserver implements Observer {

@Override

public void update() {

Log.d("TAG", "notify Kitty");

}

@Override

public String toString() {

return "Kitty";

}

}

使用:

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Observer tomObserver = new TomObserver(), kittyObserver = new KittyObserver();

Observable observable = new ConcreteObservable();

observable.register(tomObserver);

observable.register(kittyObserver);

observable.notifyObservers();

observable.removeObserver(tomObserver);

observable.notifyObservers();

}

}

打印日志

D/TAG: Tom register

D/TAG: Kitty register

D/TAG: notify Tom

D/TAG: notify Kitty

D/TAG: Tom remove

D/TAG: notify Kitty

观察者模式在RxJava中的应用

RxJava中有四个概念,Observable(被观察者)、Observer(观察者)、subscribe(订阅)、事件,

Observer和Observable通过subscribe方法实现订阅,从而Observable发送事件时,Observer可以收到相关通知。

与标准观察者模式不同的是,RxJava除了onNext(对应标准观察者模式的notifyObservers())事件以外,还有onError()和onComplete(),当Observable发送完一系列onNext()事件后,必须调用onComplete()标志着事件序列的结束,中间如果出现错误,便会走到onError()事件,这两个事件均只会被调用一次,且是相互排斥的,即走到了onComplete()就不会走到onError(),反之亦然。

基本实现

Observable(被观察者)

Observable observable = Observable.create(emitter -> {

emitter.onNext("Hello, observer");

emitter.onComplete();

});

可以看到通过Observable.create()方法创建了Observable对象,方法中传入了ObservableOnSubscribe对象,这个类中使用了泛型,这里的泛型就对应着onNext()事件传入的参数类型,以上例子这里的数据类型是String,在传入的ObservableOnSubscribe对象中,重写了subscribe方法,上述例子发送了一个onNext()事件,又发送了一个onComplete()事件,告诉Observer事件序列结束,不会再有新的onNext()事件。

当然,Observable对象并不止这一种创建方式,RxJava提供了很多相关的API,例如fromArray()、just()等等,暂且按下不表。

Observer(观察者)

Observer observer = new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d("TAG", "onSubscribe");

}

@Override

public void onNext(String o) {

Log.d("TAG", o);

}

@Override

public void onError(Throwable e) {

Log.d("TAG", "onError");

}

@Override

public void onComplete() {

Log.d("TAG", "onComplete");

}

};

创建Observer对象需要重写四个方法,可以看到其中三个重写的方法刚好对应三个事件,可以猜测,Observable发送的事件应该是交由对应的方法处理,但是多出来的onSubscribe()方法是做什么的呢?onSubscribe()方法是在Observable发送事件前被调用的,稍后会说到这点。

当然,RxJava中的观察者对象并不止Observer这一个类,RxJava还提供了一些其他的类供实现,例如Consumer等。

subscribe(订阅)

observable.subscribe(observer);

这一步就非常简单,但是会发现这里有个奇怪的地方,正常流程应该是观察者订阅被观察者,但是这里却是被观察者订阅观察者,显然,observer.subscribe(observable)这样的写法更加容易让读者接受

过如果把 API 设计成 observer.subscribe(observable) / subscriber.subscribe(observable) ,虽然更加符合思维逻辑,但对流式 API 的设计就造成影响了,比较起来明显是得不偿失的。

以上引用扔物线的一段话

RxJava中线程控制

有一些读者一定好奇,说了半天,好像也没有看到实现了异步呀,别着急,这就介绍RxJava是如何在这个链式编程中实现异步的。

我们看一下下面的示例代码

Observable

.create((ObservableOnSubscribe) emitter -> {

//模拟网络访问流程

Log.d("TAG", "subscribe " + Thread.currentThread().getName());

Thread.sleep(200);

emitter.onNext("json ");

emitter.onComplete();

})

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d("TAG", "onSubscribe " + Thread.currentThread().getName());

}

@Override

public void onNext(String s) {

Log.d("TAG", s + Thread.currentThread().getName());

}

@Override

public void onError(Throwable e) {

Log.d("TAG", "onError " + Thread.currentThread().getName());

}

@Override

public void onComplete() {

Log.d("TAG", "onComplete " + Thread.currentThread().getName());

}

});

以下是日志

D/TAG: onSubscribe main

D/TAG: subscribe RxCachedThreadScheduler-1

D/TAG: json main

D/TAG: onComplete main

我们发现,Observable发送事件的方法是运行在子线程的,而Observer处理事件的方法均是运行在主线程(UI线程),而我们仅仅只是增加了两行代码,就实现了异步编程,是不是很方便呢?但是有一个例外,onSubscribe()方法根据日志打印,是运行在主线程的,那么它真的就是和其他的事件一样,由于增加了两行代码,运行在了主线程吗?我们让这个任务在子线程运行,再看看打印的日志

D/TAG: onSubscribe Thread-4

D/TAG: subscribe RxCachedThreadScheduler-1

D/TAG: json main

D/TAG: onComplete main

由此我们知道,onSubscribe()既不是运行在发送事件的线程,也不是运行在处理事件的线程,而是运行在当前线程,具体这是为什么呢,我们后面会介绍。现在我们先来看一下,增加的两行代码究竟是什么意思呢?

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

subscribeOn(Scheduler scheduler)方法定义了发送事件运行的线程,而observeOn(Scheduler scheduler)方法则是指定处理事件运行的线程,RxJava中也指定了一些可以直接使用的Scheduler

AndroidSchedulers.mainThread()

Android主线程,即UI线程

Schedulers.newThread()

创建一个新的线程

Schedulers.io()

用于 IO 密集型任务,如果异步阻塞 IO 操作。

Schedulers.computation()

用于使用计算任务,如事件循环和回调处理

Schedulers.trampoline()

当前线程

Schedulers.single()

单线程,如果线程中有正在处理的任务,新来的任务会进入等待队列

Schedulers.from(Executor executor)

指定一个线程池

常用Api

创建操作符

1. create()

有什么用

创建一个Observable

怎么用

Observable

.create((ObservableOnSubscribe) emitter -> {

emitter.onNext("1");

emitter.onNext("2");

emitter.onNext("3");

emitter.onComplete();

})

.subscribe((s -> Log.d(TAG, "onNext: " + s)));

日志打印

D/MainActivity: onNext: 1

D/MainActivity: onNext: 2

D/MainActivity: onNext: 3

2. just()

有什么用

传入不超过十个对象,依次发送

怎么用

Observable.just(1, 3, 5)

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

}

@Override

public void onNext(Integer integer) {

Log.d(TAG, "onNext: " + integer);

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete");

}

});

日志打印

D/MainActivity: onNext: 1

D/MainActivity: onNext: 3

D/MainActivity: onNext: 5

D/MainActivity: onComplete

3. fromArray()

有什么用

与just()类似,只不过fromArray()可以传入超过10个item,也可以传入数组、集合等

怎么用

Integer[] array = {1, 3, 5};

Observable.fromArray(array)

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

}

@Override

public void onNext(Integer integer) {

Log.d(TAG, "onNext: " + integer);

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete");

}

});

日志打印

D/MainActivity: onNext: 1

D/MainActivity: onNext: 3

D/MainActivity: onNext: 5

D/MainActivity: onComplete

注意:这里的数组必须是对象数组,而不能是基本类型数组

4. fromCallable()

有什么用

这里的 Callable 是 java.util.concurrent 中的 Callable,Callable 和 Runnable 的用法基本一致,只是它会返回一个结果值,这个结果值就是发给观察者的。

怎么用

Observable.fromCallable(() -> 1)

.subscribe(integer -> Log.d(TAG, "accept" + integer));

日志打印

D/MainActivity: accept: 1

5. timer()

有什么用

指定时间倒计时结束后,会发送一个0L的值给观察者

怎么用

Observable.timer(5, TimeUnit.SECONDS)

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe");

}

@Override

public void onNext(Long aLong) {

Log.d(TAG, "onNext: " + aLong);

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

日志打印

2019-05-20 21:59:42.912 5248-5248/com.danc.calendartext D/MainActivity: onSubscribe

2019-05-20 21:59:47.918 5248-5302/com.danc.calendartext D/MainActivity: onNext: 0

可以看到,onSubscribe之后隔了5s中,接收到onNext事件

6. interval()

有什么用

每隔指定时间发送一个事件,这个事件包含一个数字,从0开始,每次自增1

怎么用

Observable.interval(0, 1, TimeUnit.SECONDS)

.subscribe(aLong -> {

Log.d(TAG, "计时(s): " + aLong);

});

日志打印

2019-05-20 22:03:29.786 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 0

2019-05-20 22:03:30.786 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 1

2019-05-20 22:03:31.786 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 2

2019-05-20 22:03:32.787 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 3

2019-05-20 22:03:33.786 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 4

2019-05-20 22:03:34.786 5375-5420/com.danc.calendartext D/MainActivity: 计时(s): 5

转化操作符

1. map()

有什么用

将被观察者发送的数据类型转换为其他类型

怎么用

以下实例将Integer类型转换为String

Observable.just(1, 3, 5)

.map(integer -> "--" + integer)

.subscribe(s -> Log.d(TAG, "accept: " + s));

日志打印

2019-05-20 22:05:58.079 5494-5494/com.danc.calendartext D/MainActivity: accept: --1

2019-05-20 22:05:58.079 5494-5494/com.danc.calendartext D/MainActivity: accept: --3

2019-05-20 22:05:58.079 5494-5494/com.danc.calendartext D/MainActivity: accept: --5

2. flatMap()

有什么用

这个方法可以将事件序列中的元素进行整合加工,返回一个新的被观察者。

怎么用

flatMap() 其实与 map() 类似,但是 flatMap() 返回的是一个 Observerable。现在用一个例子来说明 flatMap() 的用法。

假设一个有一个 Person 类,这个类的定义如下:

public class Person {

private String name;

private List planList = new ArrayList<>();

public Person(String name, List planList) {

this.name = name;

this.planList = planList;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public List getPlanList() {

return planList;

}

public void setPlanList(List planList) {

this.planList = planList;

}

}

Person 类有一个 name 和 planList 两个变量,分别代表的是人名和计划清单。

Plan 类的定义如下:

public class Plan {

private String time;

private String content;

private List actionList = new ArrayList<>();

public Plan(String time, String content) {

this.time = time;

this.content = content;

}

public String getTime() {

return time;

}

public void setTime(String time) {

this.time = time;

}

public String getContent() {

return content;

}

public void setContent(String content) {

this.content = content;

}

public List getActionList() {

return actionList;

}

public void setActionList(List actionList) {

this.actionList = actionList;

}

}

现在有一个需求就是要将 Person 集合中的每个元素中的 Plan 的 action 打印出来。

首先用 map() 来实现这个需求看看:

Observable.fromIterable(personList)

.map(new Function < Person, List < Plan >> () {

@Override

public List < Plan > apply(Person person) throws Exception {

return person.getPlanList();

}

})

.subscribe(new Observer < List < Plan >> () {

@Override

public void onSubscribe(Disposable d) {

}

@Override

public void onNext(List < Plan > plans) {

for (Plan plan: plans) {

List < String > planActionList = plan.getActionList();

for (String action: planActionList) {

Log.d(TAG, "==================action " + action);

}

}

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

可以看到 onNext() 用了嵌套 for 循环来实现,如果代码逻辑复杂起来的话,可能需要多重循环才可以实现。

现在看下使用 flatMap() 实现:

Observable.fromIterable(personList)

.flatMap(new Function < Person, ObservableSource < Plan >> () {

@Override

public ObservableSource < Plan > apply(Person person) {

return Observable.fromIterable(person.getPlanList());

}

})

.flatMap(new Function < Plan, ObservableSource < String >> () {

@Override

public ObservableSource < String > apply(Plan plan) throws Exception {

return Observable.fromIterable(plan.getActionList());

}

})

.subscribe(new Observer < String > () {

@Override

public void onSubscribe(Disposable d) {

}

@Override

public void onNext(String s) {

Log.d(TAG, "==================action: " + s);

}

@Override

public void onError(Throwable e) {

}

@Override

public void onComplete() {

}

});

从代码可以看出,只需要两个 flatMap() 就可以完成需求,并且代码逻辑非常清晰。

组合操作符

1. zip()

有什么用

将两个被观察者事件整合发送给观察者,事件数量与两个观察这种事件数量较小的相同

怎么用

Observable.zip(Observable.intervalRange(1, 5, 1, 2, TimeUnit.SECONDS)

.map(aLong -> {

String s1 = "A" + aLong;

Log.d(TAG, "===================A 发送的事件 " + s1);

return s1;

}).subscribeOn(Schedulers.io()),

Observable.intervalRange(1, 6, 1, 1, TimeUnit.SECONDS)

.map(aLong -> {

String s2 = "B" + aLong;

Log.d(TAG, "===================B 发送的事件 " + s2);

return s2;

}).subscribeOn(Schedulers.io()),

(s, s2) -> {

String res = s + s2;

return res;

})

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "===================onSubscribe ");

}

@Override

public void onNext(String s) {

Log.d(TAG, "===================onNext " + s);

}

@Override

public void onError(Throwable e) {

Log.d(TAG, "===================onError ");

}

@Override

public void onComplete() {

Log.d(TAG, "===================onComplete ");

}

});

日志打印:

2019-05-20 22:19:10.293 6183-6183/com.danc.calendartext D/MainActivity: ===================onSubscribe

2019-05-20 22:19:11.308 6183-6210/com.danc.calendartext D/MainActivity: ===================A 发送的事件 A1

2019-05-20 22:19:11.308 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B1

2019-05-20 22:19:11.308 6183-6209/com.danc.calendartext D/MainActivity: ===================onNext A1B1

2019-05-20 22:19:12.307 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B2

2019-05-20 22:19:13.307 6183-6210/com.danc.calendartext D/MainActivity: ===================A 发送的事件 A2

2019-05-20 22:19:13.307 6183-6210/com.danc.calendartext D/MainActivity: ===================onNext A2B2

2019-05-20 22:19:13.307 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B3

2019-05-20 22:19:14.308 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B4

2019-05-20 22:19:15.306 6183-6210/com.danc.calendartext D/MainActivity: ===================A 发送的事件 A3

2019-05-20 22:19:15.307 6183-6210/com.danc.calendartext D/MainActivity: ===================onNext A3B3

2019-05-20 22:19:15.307 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B5

2019-05-20 22:19:16.307 6183-6209/com.danc.calendartext D/MainActivity: ===================B 发送的事件 B6

2019-05-20 22:19:17.307 6183-6210/com.danc.calendartext D/MainActivity: ===================A 发送的事件 A4

2019-05-20 22:19:17.308 6183-6210/com.danc.calendartext D/MainActivity: ===================onNext A4B4

2019-05-20 22:19:19.307 6183-6210/com.danc.calendartext D/MainActivity: ===================A 发送的事件 A5

2019-05-20 22:19:19.307 6183-6210/com.danc.calendartext D/MainActivity: ===================onNext A5B5

2019-05-20 22:19:19.307 6183-6210/com.danc.calendartext D/MainActivity: ===================onComplete

功能操作符

1. delay()

有什么用

订阅后,延迟一段时间发送事件

怎么用

Observable.just(1, 3, 5)

.delay(2, TimeUnit.SECONDS)

.subscribe(integer -> Log.d(TAG, "accept: " + integer));

打印日志

2019-05-20 22:24:53.879 6430-6430/com.danc.calendartext D/MainActivity: onSubscribe

2019-05-20 22:24:55.881 6430-6475/com.danc.calendartext D/MainActivity: accept: 1

2019-05-20 22:24:55.881 6430-6475/com.danc.calendartext D/MainActivity: accept: 3

2019-05-20 22:24:55.882 6430-6475/com.danc.calendartext D/MainActivity: accept: 5

从日志可以暗处,订阅之后延迟2s开始发送事件

2. doOnNext()

有什么用

每次收到onNext()事件,先执行doOnNext()

怎么用

Observable.create((ObservableOnSubscribe) e -> {

e.onNext(1);

e.onNext(2);

e.onNext(3);

e.onComplete();

})

.doOnNext(integer -> Log.d(TAG, "doOnNext " + integer))

.subscribe(new Observer < Integer > () {

@Override

public void onSubscribe(Disposable d) {

Log.d(TAG, "onSubscribe ");

}

@Override

public void onNext(Integer integer) {

Log.d(TAG, "onNext " + integer);

}

@Override

public void onError(Throwable e) {

Log.d(TAG, "onError ");

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete ");

}

});

日志打印

D/MainActivity: onSubscribe

D/MainActivity: doOnNext 1

D/MainActivity: onNext 1

D/MainActivity: doOnNext 2

D/MainActivity: onNext 2

D/MainActivity: doOnNext 3

D/MainActivity: onNext 3

D/MainActivity: onComplete

想要查看更多的RxJava2的API,可以看下面这篇文章。这篇文章更像是查阅的资料,只需要通览了解一遍即可,熟悉常用的API,其余有个印象,需要的时候再查阅

RxJava2 只看这一篇文章就够了 - 掘金

生命周期管理

RxJava固然很好用,但是使用不当,很容易造成内存泄漏。

比如,使用RxJava发布一个订阅后,当Activity被finish,此时订阅逻辑还未完成,如果没有及时取消订阅,就会导致Activity无法被回收,从而引发内存泄漏。

目前,针对以上这种情况,主流的有两种解决方案:

通过封装,手动控制每一次订阅,在合适的时机取消订阅

使用RxLifecycle,关注Fragment、Activity的生命周期,在onDestroy()生命周期中自动取消订阅

手动实现

以下是基于MVP架构封装的

protected CompositeDisposable compositeDisposable;

@UiThread

public void attachView(V view) {

mView = view;

compositeDisposable = new CompositeDisposable();

}

@UiThread

public void detachView() {

mView = null;

if (compositeDisposable != null) {

compositeDisposable.clear();

compositeDisposable = null;

}

}

如何使用

在每次发生订阅关系时,将返回的Disposable实例保存在CompositeDisposable中,在onDestroy()生命周期解除所有的订阅关系

RxLifecycle

1. 添加依赖

在项目中添加以下依赖

implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'

implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'

implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'

2. 绑定生命周期

RxLifecycle提供了大量的Activity、Fragment以供继承

5213fe112fa9

RxLifecycle支持的Component、

代码如下:

public class MainActivity extends RxAppCompatActivity {

...

...

}

使用bindToLifecycle()

以Activity为例,在Activity中使用bindToLifecycle()方法,完成Observable发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对Observable订阅,代码如下:

public class MainActivity extends RxAppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 当执行onDestory()时, 自动解除订阅

Observable.interval(1, TimeUnit.SECONDS)

.doOnDispose(new Action() {

@Override

public void run() throws Exception {

Log.i(TAG, "Unsubscribing subscription from onCreate()");

}

})

.compose(this.bindToLifecycle())

.subscribe(new Consumer() {

@Override

public void accept(Long num) throws Exception {

Log.i(TAG, "Started in onCreate(), running until onDestory(): " + num);

}

});

}

}

下一篇文章将针对订阅流程以及线程管理的源码进行分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值