为什么要做生命周期管理
使用 RxJava 这个库做开发也已经很多年了,从刚开始使用到现在也经历了很多个阶段,中间也遇到了很多问题,今天我们就 RxJava 的生命周期问题好好聊一聊。
- RxJava 怎么用,想必大家都是知道的:
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
复制代码
- 这样就是一个简单的异步处理,但是如果只是这样使用肯定是不行,因为在 Android 开发过程中,如果在进行耗时操作的时候,操作还没有结束,这个时候退出的当前 Activity,这个时候,这段代码的处理并不会因为 Activity 的退出而结束,就会导致内存泄漏等问题,严重的时候甚至会导致 APP 闪退。
如何管理生命周期
那么,如何对 RxJava 的生命周期进行管理呢?RxJava 给我们提供了
CompositeDisposable
这个类,用于对 RxJava 的管理。
val disposable = Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
val disposables = CompositeDisposable()
disposables.add(disposable)
disposables.clear()
复制代码
- 每次使用 RxJava,都将其生成的
Disposable
对象添加到CompositeDisposable
对象中,并在每个界面结束的时候,调用CompositeDisposable
对象的clear()
方法取消事件。 - 在较新版本的 RxJava 使用过程中,我们会发现,如果没有对
subscribe
方法的返回参数进行处理,studio
就会报黄色的警告,这是因为 RxJava 在subscribe
方法添加了@CheckReturnValue
注解,要求我们对其返回值进行处理。
这就是我第一阶段的处理,在每次使用到 RxJava 的时候,添加
CompositeDisposable
,并在Activity
的onDestroy
方法中进行处理。
简易管理的第一个版本
从上面的处理引申出来,无非是将相关操作封装到基类中,提供一个方法
addDisposable
来将 RxJava 请求添加到生命周期管理。 后来使用了 Google Jetpack 中的ViewModel
,就将最后的清理操作放到了ViewModel
的onCleared
方法中。
- 但是,这些处理都有一个共同的问题,那就是不够优雅。
addDisposable(
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
)
val disposable = Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
// onNext
}, {
// onError
})
addDisposable(disposable)
复制代码
- 每次在使用 RxJava 的时候都要调用
addDisposable
,一次两次没什么,但如果项目中用的多了,就会觉得很繁琐,所以,我产生对其进行优化的念头。 - 第一个想法就是:如何让他在链式的调用的过程中,完成生命周期管理的绑定。
- 这样的话就需要我们在 RxJava 的类中添加方法,如果是 Java 开发当然是办不到的,我们不能修改 RxJava 的源码,但是在 Kotlin 中,我们可以使用 拓展方法 来达到这一效果。
- 首先,要对生命周期进行统一的管理,我们就需要把生命周期管理相关的方法抽取成一个接口:
interface RxLifecycleOwner {
/** RxJ 生命周期管理 */
var disposables: CompositeDisposable?
/**
* 将 Rx 添加到生命周期管理
*/
fun addDisposable(dis: Disposable) {
disposables?.add(dis)
}
/**
* 处理所有添加到生命周期管理的事件
*/
fun disposeAll() {
disposables?.clear()
disposables = null
}
}
复制代码
- Kotlin 中接口的方法是可以有默认实现的。
- 然后添加 扩展方法:
/**
* 订阅并关联生命周期管理
*
* @param owner Rx 生命周期管理接口
* @param onNext 事件处理
* @param onComplete 事件完成
* @param onSubscribe 事件订阅
*
* @return [Disposable] 事件对象
*/
fun <T> Observable<T>.subscribeWithOwner(owner: RxLifecycleOwner,
onNext: Consumer<T> = Functions.emptyConsumer(),
onError: Consumer<Throwable> = Functions.ON_ERROR_MISSING,
onComplete: Action = Functions.EMPTY_ACTION,
onSubscribe: Consumer<Disposable> = Functions.emptyConsumer()
): Disposable {
val disposable = this.subscribe(onNext, onError, onComplete, onSubscribe)
owner.addDisposable(disposable)
return disposable
}
/**
* 订阅并关联生命周期管理
*
* @param owner Rx 生命周期管理接口
* @param observer 观察者对象
*/
fun <T> Observable<T>.subscribeWithOwner(owner: RxLifecycleOwner,
observer: Observer<T>
) {
this.subscribe(object : Observer<T> {
override fun onComplete() {
observer.onComplete()
}
override fun onSubscribe(d: Disposable) {
observer.onSubscribe(d)
owner.addDisposable(d)
}
override fun onNext(t: T) {
observer.onNext(t)
}
override fun onError(e: Throwable) {
observer.onError(e)
}
})
}
复制代码
- 使用时只需要实现
RxLifecycleOwner
接口,并初始化CompositeDisposable
对象就可以了。
class BaseViewModel
: ViewModel(), RxLifeCycleOwner {
/** Rx 生命周期管理 */
override var disposables: CompositeDisposable? = CompositeDisposable()
override fun onCleared() {
// 处理 Rx 事件
disposeAll()
}
}
class MainViewModel : BaseViewModel() {
fun doSomething() {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(this, {
// onNext
}, {
// onError
})
}
}
复制代码
- 这样,第一个版本就完成了,每次使用 RxJava 都无需多余的代码,生命周期管理也能链式调用。
简易管理的第二个版本
经过上面的一通操作,我们已经对 RxJava 的生命周期管理进行了一定的简化,但是还是觉得复杂怎么办,为什么每次使用都要实现
RxLifecycleOwner
接口啊,每次都要手动去取消事件,好麻烦的样子,有没有更好的解决方案? 这时,LiveData
给了我灵感。
- 众所周知,
LiveData
是有生命周期感知的,他内部有一个LifecycleBoundObserver
类,通过实现LifecycleEventObserver
接口实现了对 Activity、Fragment 的生命周期感知,LifecycleEventObserver
中有onStateChanged
方法,会在Activity、Fragment 生命周期方法后回调,于是,就有了接下来的操作。
/**
* Rx 生命周期观察者
*
* @param lifecycleOwner Android 生命周期管理接口
*/
class RxLifecycleObserver(lifecycleOwner: LifecycleOwner) : LifecycleEventObserver, RxLifecycleOwner {
override var disposables: CompositeDisposable? = null
init {
disposables = CompositeDisposable()
// 将当前观察者对象添加到 Android 生命周期管理
lifecycleOwner.lifecycle.addObserver(this)
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) {
// 生命周期走到了 onDestroy,消费所有事件
disposeAll()
// 移除观察者
source.lifecycle.removeObserver(this)
// 从集合中移除引用
rxLifecycles.remove(source)
}
}
}
复制代码
- 有些地方可能是在找不到
LifecycleOwner
,但有需要生命周期管理,所以保留了RxLifecycleOwner
接口。
/**
* HashMap 对象,保存 Rx、Android 生命周期管理对象
*/
internal val rxLifecycles = hashMapOf<LifecycleOwner, RxLifecycleObserver>()
/**
* 根据 Android 生命周期对象获取 Rx 生命周期管理对象
*
* @param owner Android 生命周期对象
*
* @return Rx 生命周期管理对象
*/
internal fun getObserver(owner: LifecycleOwner): RxLifecycleObserver {
var observer: RxLifecycleObserver?
if (rxLifecycles.containsKey(owner)) {
// 集合中已包含观察者对象
observer = rxLifecycles[owner]
if (observer != null) {
// 且不为空,返回已有的观察者对象
return observer
}
}
// 没有已存在的,新建观察者对象
observer = RxLifecycleObserver(owner)
// 添加到 Map 集合以复用
rxLifecycles[owner] = observer
return observer
}
复制代码
- 使用 Map 集合保存观察者对象以复用。
/**
* 订阅并关联生命周期管理
*
* @param owner Android 生命周期接口
* @param onNext 事件处理
* @param onComplete 事件完成
* @param onSubscribe 事件订阅
*
* @return [Disposable] 事件对象
*/
fun <T> Observable<T>.subscribeWithOwner(owner: LifecycleOwner,
onNext: Consumer<T> = Functions.emptyConsumer(),
onError: Consumer<Throwable> = Functions.ON_ERROR_MISSING,
onComplete: Action = Functions.EMPTY_ACTION,
onSubscribe: Consumer<Disposable> = Functions.emptyConsumer()
): Disposable {
val disposable = this.subscribe(onNext, onError, onComplete, onSubscribe)
getObserver(owner).addDisposable(disposable)
return disposable
}
/**
* 订阅并关联生命周期管理
*
* @param owner Android 生命周期接口
* @param observer 观察者对象
*/
fun <T> Observable<T>.subscribeWithOwner(owner: LifecycleOwner,
observer: Observer<T>
) {
this.subscribe(object : Observer<T> {
override fun onComplete() {
observer.onComplete()
}
override fun onSubscribe(d: Disposable) {
observer.onSubscribe(d)
getObserver(owner).addDisposable(d)
}
override fun onNext(t: T) {
observer.onNext(t)
}
override fun onError(e: Throwable) {
observer.onError(e)
}
})
}
复制代码
- 这样使用起来更方便了。
class MainActivity : AppCompatActivity() {
fun doSomething() {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(this, {
// onNext
}, {
// onError
})
}
}
复制代码
- Activity 中使用。
class BaseViewModel : ViewModel(), LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_CREATE -> onCreate(source)
Lifecycle.Event.ON_START -> onStart(source)
Lifecycle.Event.ON_RESUME -> onResume(source)
Lifecycle.Event.ON_PAUSE -> onPause(source)
Lifecycle.Event.ON_STOP -> onStop(source)
Lifecycle.Event.ON_DESTROY -> onDestroy(source)
Lifecycle.Event.ON_ANY -> {
}
}
}
}
class MainViewModel : BaseViewModel() {
override fun onCreate(source: LifecycleOwner) {
Observable.create<String> {
// do something
it.onNext("")
it.onComplete()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWithOwner(source, {
// onNext
}, {
// onError
})
}
}
复制代码
最后
- 好了,现在一个完整的 RxJava 的生命周期处理就完成了,一共不到 300 行代码。
- Github 地址在这里 欢迎取用。