RxLifecycle:绑定你的Observable到生命周期上

以云看科技 2024-07-05 15:03:46
前言

RxJava 是 Android 开发中的一件神器,但我们在 Activity 或 Fragment 里使用 RxJava 的时候要注意,没在恰当时机执行 Dispose 或终止 Observable 的话会导致内存泄漏。下面这段代码中,Consumer 匿名内部类持有 Activity 的引用,当 Activity 销毁时 Observable 并没有被中止或切断与 Observer 的联系(未 Dispose),所以就造成了内存泄漏。

Observable.interval(0, 2, TimeUnit.SECONDS) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long n) throws Exception { } });

要避免这种情况的话,我们可以使用 Rx 官方提供的 Dispose 方法来在 Activity 销毁时手动切断 Observable 与 Observer 的联系(但是 Observable 还会继续发射数据):

private Disposable disposable;@Overridepublic void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); disposable = Observable.interval(0, 2, TimeUnit.SECONDS) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long n) throws Exception { } });}@Overrideprotected void onDestroy() { super.onDestroy(); disposable.dispose();}

这样写的体验是割裂的,你需要保存一堆 Disposable 的引用(当然你也可以使用 CompositeDisposable),然后在销毁时再「手工进行」Dispose。

探索

有没有更优雅些的办法呢?答案是有的。在 Rx 官方提供的一些操作符中可以让我们提前中止 Observable 与 Observer 的联系,例如 TakeUtil 操作符:

假设Observable.takeUtil(ObservableB).subscribe(Observer)。当 ObservableB 发射第一个数据时,Observable 立刻被 Complete,同时立刻调用了 Observer 的 onComplete() 方法,观察结束后立刻释放对 Observer 的引用。

于是,脑洞大开的我们可以创建一个如下的变换操作符:

public BindLifecycleTransformer<T> implements ObservableTransformer<T, T> { private final BehaviorProcessor<Integer> lifecycleBehavior; public BindLifecycleObservableTransformer(@NonNull BehaviorProcessor<Integer> lifecycleBehavior) { this.lifecycleBehavior = lifecycleBehavior; } @Override public ObservableSource<T> apply(Observable<T> upstream) { return upstream.takeUntil( lifecycleBehavior.skipWhile(new Predicate<Integer>() { @Override public boolean test(@LifecyclePublisher.Event Integer event) throws Exception { return event != LifecyclePublisher.ON_DESTROY_VIEW && event != LifecyclePublisher.ON_DESTROY && event != LifecyclePublisher.ON_DETACH; } }).toObservable() ); }}

接下来只要在 Activity 里创建一个用于记录当前所在生命周期的 LifecycleBehavior,然后就可以使用 compose(new BindLifecycleObservableTransformer(lifecycleBehavior)) 来绑定你的 Observable 到 Activity 的生命周期上了。

但是这样还是需要手动维护个 LifecycleBehavior。有没有办法连 LifecycleBehavior 都不写呢?答案依然是有的。

我们可以通过一个独立的 HeadlessFragment 来维护 LifecycleBehavior,然后想监听哪个 Activity 或 Fragment 的生命周期的话,只要将 HeadlessFragment 插入其中就行了,FragmentManager 会主动同步 HeadlessFragment 与父 Activity/Fragment 之间的生命周期。

RxLifecycle

我们将上述的工作封装成了一个开源库 RxLifecycle ⇦猛戳,你可以在其中查阅上面提到的所有代码。它允许你仅用一句话绑定你的 Observable 到 Activity/Fragment 的生命周期上:

Observable.interval(0, 2, TimeUnit.SECONDS) .compose(RxLifecycle.bind(MainActivity.this).<Long>withObservable()) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long n) throws Exception { } });

我们在仓库中还提供了个 DEMO,以便详细介绍 RxLifecycle 的全部功能。

作者:nekocode

出处:https://zhuanlan.zhihu.com/p/24992118

0 阅读:0
以云看科技

以云看科技

感谢大家的关注