Rxjava解除订阅③:RxLife

Rxjava解除订阅三部曲:

  • Rxjava解除订阅①:自带方式和RxLifeCycle

  • Rxjava解除订阅②:AutoDispose

  • Rxjava解除订阅③:RxLife

前言

  • Rxjava解除订阅①:自带方式和RxLifeCycle
  • Rxjava解除订阅②:AutoDispose
    本篇RxLife是国人封装的库,我看着也挺好,比较符合国人的使用习惯,实现原理跟AutoDispose很相似,源码也易读,不像老外们写的那么饶,所以也给大家们分析下。

使用

官方介绍RxLife很厉害:
RxLife,相较于trello/RxLifecycle、uber/AutoDispose,具有如下优势:

  • 直接支持在主线程回调
  • 支持在子线程订阅观察者
  • 简单易用,学习成本低
  • 性能更优,在实现上更加简单
看着挺牛的

按照官方文档一步一步来就行,先集成maven:

dependencies {
   //rxjava2
   implementation 'com.ljx.rxlife2:rxlife-rxjava:2.0.0'
       
   //rxjava3
   implementation 'com.ljx.rxlife3:rxlife-rxjava:3.0.0'
}

注:由于Google在19年就停止了非AndroidX的库的更新,故rxlife仅支持AndroidX项目,请尽快将项目迁移至AndroidX

1.Activity/Fragment:

Activity/Fragment销毁时,自动关闭RxJava管道:

Observable.timer(5, TimeUnit.SECONDS)
    .as(RxLife.as(this))     //此时的this Activity/Fragment对象
    .subscribe(aLong -> {
        Log.e("LJX", "accept =" + aLong);
    });
2.View

View被移除时,自动关闭RxJava管道

Observable.timer(5, TimeUnit.SECONDS)
    .as(RxLife.as(this))  //此时的this 为View对象
    .subscribe(aLong -> {
        Log.e("LJX", "accept =" + aLong);
    });
3.ViewModel

Activity/Fragment销毁时,自动关闭RxJava管道,ViewModel需要继承ScopeViewModel类,如下

public class MyViewModel extends ScopeViewModel {

    public MyViewModel(@NonNull Application application) {
        super(application);
    }
   
    public void test(){
        Observable.interval(1, 1, TimeUnit.SECONDS)
            .as(RxLife.asOnMain(this))  //继承ScopeViewModel后,就可以直接传this
            .subscribe(aLong -> {
                Log.e("LJX", "MyViewModel aLong=" + aLong);
            });
    }
}

注意:一定要在Activity/Fragment通过以下方式获取ViewModel对象,否则RxLife接收不到生命周期的回调

MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
4.任意类

Activity/Fragment销毁时,自动关闭RxJava管道,任意类需要继承BaseScope类,如P层:

public class Presenter extends BaseScope {

    public Presenter(LifecycleOwner owner) {
        super(owner); //添加生命周期监听
    }

    public void test(){
        Observable.interval(1, 1, TimeUnit.SECONDS)
            .as(RxLife.as(this)) //继承BaseScope后,就可以直接传this
            .subscribe(aLong -> {
                Log.e("LJX", "accept aLong=" + aLong);
            });
    }
}
5.kotlin用户

由于as是kotlin中的一个关键字,所以在kotlin中,我们并不能直接使用as(RxLife.as(this)),可以如下编写

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
    .`as`(RxLife.`as`(this))
    .subscribe { aLong ->
        Log.e("LJX", "accept=" + aLong)
    }

当然,相信没多少人会喜欢这种写法,故,RxLife针对kotlin用户,新增更为便捷的写法,如下:

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
    .life(this)
    .subscribe { aLong ->
        Log.e("LJX", "accept=" + aLong)
    }

使用life 操作符替代as操作符即可,其它均一样

6.小彩蛋 asOnMain操作符

RxLife还提供了asOnMain操作符,它可以指定下游的观察者在主线程中回调,如下:

Observable.timer(5, TimeUnit.SECONDS)
    .as(RxLife.asOnMain(this))
    .subscribe(aLong -> {
        //在主线程回调
       Log.e("LJX", "accept =" + aLong);
    });

        //等价于
Observable.timer(5, TimeUnit.SECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .as(RxLife.as(this))
    .subscribe(aLong -> {
        //在主线程回调
        Log.e("LJX", "accept =" + aLong);
    });

kotlin 用户使用lifeOnMain替代asOnMain操作符,其它均一样。
注意: RxLife类里面as操作符,皆适用于Flowable、ParallelFlowable、Observable、Single、Maybe、Completable这6个被观察者对象

7.混淆

RxLife作为开源库,可混淆,也可不混淆,如果不希望被混淆,请在proguard-rules.pro文件添加以下代码:

-keep class com.rxjava.rxlife.**{*;}

以上这些全部是官方文档,我只是搬运过来。从上述看来,RxLife是基于google的jetpack开发的,仅支持androidx及以上版本,不向下兼容。对于现有的商业应用来说,随意升级target是很危险的事情,从而也限制了RxLife的使用场景。

源码解析

Rxjava解除订阅③:RxLife_第1张图片
  • 1.Activity/Fragment
public static  RxConverter as(LifecycleOwner owner) {
        return as(owner, Event.ON_DESTROY, false);
    }

    public static  RxConverter as(LifecycleOwner owner, Event event) {
        return as(owner, event, false);
    }

    public static  RxConverter asOnMain(LifecycleOwner owner) {
        return as(owner, Event.ON_DESTROY, true);
    }
    //上面三个方法 最终调用的此方法
    private static  RxConverter as(LifecycleOwner owner, Event event, boolean onMain) {
        return as(LifecycleScope.from(owner, event), onMain);
    }

同AutoDispose一样基于LifecycleOwner实现生命周期监控。
跟RxLifeCycle和AutoDispose一样,RxLife可以自动识别生命周期,也可以指定生命周期解绑。但跟他们不同的是,所谓自动解绑,是指定在Event.ON_DESTROY的生命周期解除绑定,可以说是没有RxLifeCycle和AutoDispose那么智能。
asasMain的区别只是最后一个参数不同,不难猜测,底层肯定是主动切到了主线程。
继续追踪as方法可以看到这个核心方法:

private void subscribeActual(Observer observer) {
        Observable upStream = this.upStream;
        if (onMain) {
            upStream = upStream.observeOn(AndroidSchedulers.mainThread());
        }
        upStream.onTerminateDetach().subscribe(new LifeObserver<>(observer, scope));
    }

果然是调用了 upStream.observeOn(AndroidSchedulers.mainThread());切了线程。

那么解绑绑定的核心方法就是LifecycleScope.from(owner, event),继续追踪下去:

static LifecycleScope from(LifecycleOwner owner, Event event) {
        return new LifecycleScope(owner.getLifecycle(), event);
    }

LifecycleScope实现了LifecycleEventObserver接口,重写了onStateChanged方法:

@Override
    public void onStateChanged(@NotNull LifecycleOwner source, Event event) {
        if (event.equals(this.event)) {
            disposable.dispose();
            source.getLifecycle().removeObserver(this);
        }
    }

此为核心代码,很简单的机制,当生命周期改变时会回调这个方法,并与设置的生命周期事件判断,如果一致则dispose,并将此监听移除。

有removeObserver那肯定也有addObserver,LifecycleScope还实现了自己写的Scope

@Override
    public void onScopeStart(Disposable d) {
        this.disposable = d;
        onScopeEnd();
        final Lifecycle lifecycle = this.lifecycle;
        if (lifecycle == null)
            throw new NullPointerException("lifecycle is null");
        lifecycle.addObserver(this);
    }

    @Override
    public void onScopeEnd() {
        final Lifecycle lifecycle = this.lifecycle;
        if (lifecycle == null)
            throw new NullPointerException("lifecycle is null");
        lifecycle.removeObserver(this);
    }

向上追踪发现AbstractLifecycleaddObserverOnMain调用onScopeStart方法,并且addObserver调用addObserverOnMain

    /**
     * 事件订阅时调用此方法
     */
    protected final void addObserver() throws Exception {
        //Lifecycle添加监听器需要在主线程执行
        if (isMainThread() || !(scope instanceof LifecycleScope)) {
            addObserverOnMain();
        } else {
            final Object object = mObject;
            AndroidSchedulers.mainThread().scheduleDirect(() -> {
                addObserverOnMain();
               ...
            });
          ...
        }
    }

还是看不出来啥时候add的,继续向上追踪,发现在LifeObserveronSubscribe调用了此方法:

final class LifeObserver extends AbstractLifecycle implements Observer {
    @Override
    public void onSubscribe(Disposable d) {
        if (DisposableHelper.setOnce(this, d)) {
            try {
                addObserver();
                downstream.onSubscribe(d);
            } catch (Throwable ex) {
                Exceptions.throwIfFatal(ex);
                d.dispose();
                onError(ex);
            }
        }
    }

细心的朋友们可能已经察觉到了,LifeObserver就是刚刚我们追踪as方法时出现过:

    private void subscribeActual(Observer observer) {
        Observable upStream = this.upStream;
        if (onMain) {
            upStream = upStream.observeOn(AndroidSchedulers.mainThread());
        }
        upStream.onTerminateDetach().subscribe(new LifeObserver<>(observer, scope));
    }

至此全部逻辑就连在了一起。

  • 2.View

自定义View的自动解绑的原理跟Activity和Fragment基本一致,唯一不同的是解绑时机。
ViewScope实现的OnAttachStateChangeListener接口,在onViewDetachedFromWindow方法中实现解除绑定。

@Override
    public void onViewDetachedFromWindow(View v) {
        disposable.dispose();
        v.removeOnAttachStateChangeListener(this);
    }

注册监听的地方跟Activity和Fragment一样,也是在onScopeStart。

  • 3.任意页面

按照官方文档描述,只要继承BaseScope就可以实现自动解绑,但实际操作中并不是所谓的只要继承就行。

public class BaseScope implements Scope, LifecycleEventObserver {

    public BaseScope(LifecycleOwner owner) {
        owner.getLifecycle().addObserver(this);
    }
}

事实上构造器得传递LifecycleOwner,那为什么官方文档上要说任意类呢,原因就像之前提到的RxLife是基于Google的jetpack来实现的,对应jetpack来说,ViewModel,LifeCycle等都有自己的生命周期,而且也都与LifecycleOwner有关,在这几个控件里自定义的组件,的确可以说是任意类。

结语

RxLife相比RxLifeCycle和AutoDispose来说,有着他自己的优势:轻量级,易用,易读,基于jetpack。缺点也很明显,只支持Androidx及以上版本,不向下兼容。项目迁移到Android X涉及到方方面面的改动,风险很大,对于这些应用来说,只能选择使用RxLifeCycle或者AutoDispose了。但google早以停掉了对Androidx以下的支持,迁移到Androidx也只是时间的问题,到时就是RxLife大放光彩的时候了。

你可能感兴趣的:(Rxjava解除订阅③:RxLife)