Rxjava解除订阅②:AutoDispose

Rxjava解除订阅三部曲:

前言

上一篇介绍了Rxjava解除订阅①:自带方式和RxLifeCycle,并且在结尾也透漏了可以解决RxLifeCycle的弊端的方法,那就是AutoDispose。其实AutoDispose大部分也是借鉴RxLifeCycle的经验,很多地方都比较相似,所以源码也比较容易阅读。github地址:AutoDispose

使用

引入:
androidX以下的版本只支持到0.8.0,android x 并且使用rxjava2,可以使用1.x版本;使用rxjava3的话可以升级到2.x版本。这里以1.3版本为主:

def autoDispose = "1.3.0"
dependencies {
    implementation "com.uber.autodispose:autodispose:${autoDispose}"
    implementation "com.uber.autodispose:autodispose-android-archcomponents:${autoDispose}"
}

应用起来也很简单:

Observable.interval(0, 2, TimeUnit.SECONDS)
                .map(aLong -> {
                    Log.d(TAG, "aLong:" + aLong);
                    return aLong == 4;
                })
               // .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY)))  //指定解绑生命周期
                .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))  // 自动识别生命周期解绑
                .subscribe(aBoolean -> Log.d(TAG, "aBoolean:" + aBoolean));

使用as操作符,传递AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))方法即可。跟RxLifeCycle一样,除了上面这个自动识别生命周期来解绑之外,也提供了AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY))在指定的生命周期解绑操作。

as操作符是什么呢?是将Observable转成一个新的对象,跟compose不同的地方在于,compose是将Observable生成的对象还是Observable。

原理

1.this是什么?

RxLifeCycle类似,也是传递当前Activity的this进去,不同的是这个this并不是Activity本身,而是LifecycleOwner。关于LifecycleOwner大家自行搜索一下,是google提供的一个生命周期管理的类。

2.生命周期是如何绑定的?

as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))

知道了this,下一步就是看生命周期是如何绑定,进而在合适的生命周期解绑rxjava。AutoDispose.autoDisposable()传递进的是一个ScopeProvider,翻译中文可以认为是一种能力的提供者,那我们传递的AndroidLifecycleScopeProvider.from(this)返回的就是一个AndroidLifecycleScopeProvider,字面意思就是说android生命周期能力提供者。

那么这俩方法的作用就知晓了:AutoDispose.autoDisposable()是进行生命周期的解绑方法,而AndroidLifecycleScopeProvider.from(this)是提供对应的生命周期方法。

AutoDispose.autoDisposable()比较简单:

public static <T> AutoDisposeConverter<T> autoDisposable(final ScopeProvider provider) {
    checkNotNull(provider, "provider == null");
    return autoDisposable(
        Completable.defer(
            () -> {
              try {
                return provider.requestScope();// 核心方法:最终调用ScopeProvider 的requestScope()
              } catch (OutsideScopeException e) {
                ...
              }
            }));
  }

这里用到了defer操作符,没啥特别的含义,可以简单的理解为懒加载,只有订阅关系成立时才会触发这个方法。

而return 的autoDisposable()方法则是返回对应的ObservableConverter。这也是因为我们的订阅关系是从Observable开始的,如果是Flowable,那么对应返回的就是FlowableConverter。而autoDisposable()内部实现了多个订阅关系的Converter,无论哪种订阅关系,都可以实现自动解绑。

最终核心的方法是调用了provider.requestScope()
一路追踪源码:

public static <E> CompletableSource resolveScopeFromLifecycle( final LifecycleScopeProvider<E> provider, final boolean checkEndBoundary)
      throws OutsideScopeException {
    E lastEvent = provider.peekLifecycle();
    CorrespondingEventsFunction<E> eventsFunction = provider.correspondingEvents();
    if (lastEvent == null) {
      throw new LifecycleNotStartedException();
    }
    E endEvent;
    try {
      endEvent = eventsFunction.apply(lastEvent);// 获取当前生命周期
    } catch (Exception e) {
      ...
    }
    return resolveScopeFromLifecycle(provider.lifecycle(), endEvent);
  }

到这,算是知晓了生命周期是从何而来,CorrespondingEventsFunction会提供给我们最后的一个生命周期方法,无论是自动识别生命周期还是指定生命周期解绑,最终都是通过CorrespondingEventsFunction得来的。为何要这么说呢?让我们回到from方法来看:

// 在指定生命周期解除绑定
public static AndroidLifecycleScopeProvider from(LifecycleOwner owner, Lifecycle.Event untilEvent) {
    return from(owner.getLifecycle(), untilEvent);
  }
// 自动解除绑定
public static AndroidLifecycleScopeProvider from(Lifecycle lifecycle) {
    return from(lifecycle, DEFAULT_CORRESPONDING_EVENTS);
  }

而自动解除绑定的生命周期判定是DEFAULT_CORRESPONDING_EVENTS是这样的:

private static final CorrespondingEventsFunction<Lifecycle.Event> DEFAULT_CORRESPONDING_EVENTS =
      lastEvent -> {
        switch (lastEvent) {
          case ON_CREATE:
            return Lifecycle.Event.ON_DESTROY;
          case ON_START:
            return Lifecycle.Event.ON_STOP;
          case ON_RESUME:
            return Lifecycle.Event.ON_PAUSE;
          case ON_PAUSE:
            return Lifecycle.Event.ON_STOP;
          case ON_STOP:
          case ON_DESTROY:
          default:
            throw new LifecycleEndedException("Lifecycle has ended! Last event was " + lastEvent);
        }
      };

这个地方可以看到DEFAULT_CORRESPONDING_EVENTS其实是CorrespondingEventsFunction的一个实例,而实现的内容是不是也很眼熟呢?这块跟RxLifeCycle一样,自动选择合适生命周期。

再往里走看看指定生命周期的from方法是啥:

public static AndroidLifecycleScopeProvider from(
      Lifecycle lifecycle, Lifecycle.Event untilEvent) {
    return from(lifecycle, new UntilEventFunction(untilEvent));
  }
//UntilEventFunction是CorrespondingEventsFunction一个具体实现类
private static class UntilEventFunction implements CorrespondingEventsFunction<Lifecycle.Event> {
    private final Lifecycle.Event untilEvent;

    UntilEventFunction(Lifecycle.Event untilEvent) {
      this.untilEvent = untilEvent;
    }

    @Override
    public Lifecycle.Event apply(Lifecycle.Event event) throws OutsideScopeException {
      return untilEvent;// 返回指定的生命周期
    }
  }

UntilEventFunctionCorrespondingEventsFunction一个具体实现类,最终apply方法也是返回了我们指定的那个生命周期。
转了一圈到此为止,我们也算是了解了生命周期是如何获取的。那么怎么解绑呢?其实这块内容跟RxLifeCycle就非常相似了:
我们继续追踪resolveScopeFromLifecycle方法到最后实现:

public static <E> CompletableSource resolveScopeFromLifecycle(
      Observable<E> lifecycle, final E endEvent, @Nullable final Comparator<E> comparator) {
    Predicate<E> equalityPredicate;
    if (comparator != null) {
      equalityPredicate = e -> comparator.compare(e, endEvent) >= 0;
    } else {
      equalityPredicate = e -> e.equals(endEvent);
    }
    return lifecycle.skip(1).takeUntil(equalityPredicate).ignoreElements();
  }

是不是跟RxLifeCycle的最终核心方法非常相似,也是用的takeUntil操作符,在指定的生命周期内,打断上层数据流,从而实现自动解绑,避免内存泄漏。

这里简单的说下操作的过程:

  • 首先skip(1)的意思是说,忽略发送的第一个生命周期,因为获取到的第一个生命周期往往都是发送订阅关系的这个生命周期,比如在onCreate中绑定,那么剩下的生命周期就是onStart,onResume,onPause,onDestory了。
  • 再然后takeUntil(equalityPredicate),这个操作符比较简单,通过对比判断当前生命周期和指定生命周期是否一致,一致则打断上面的数据流,实现解绑。
  • 最终ignoreElements忽略不执行onNext方法,只执行onComplete或者onError。

到此为止,解绑的源码也就分析完了。

对比RxLifeCycle

AutoDispose中很多都是借鉴RxLifeCycle,而设计上有些出入:

  • 1.RxLifeCycle使用需要实现RxAppCompatActivity或者RxFragment,对于商业应用来说,随随便便改动基础类是很危险的事情,从设计的角度上来讲:组合的灵活度多数情况下更优于继承。而RxLifecycle在父类中声明了一个PublishSubject,用来发射生命周期事件,这是导致其局限性的原因之一。

  • 2.在绑定生命周期的设计上,两者也截然不同。RxLifeCycle需要继承基类,然后从基类中获取生命周期发射到底层,限制了使用场景,对于MVP架构来说,Activity和Fragment作为V层负责是ui更新,具体逻辑实现要在P层实现,RxLifeCycle无法做到在P层自动解绑。而AutoDispose是基于google的LifecycleOwner实现的,这就大大增加了可扩展性,也就意味着MVP架构的P层实际上也可以直接实现自动解绑操作了。

  • 3.同上因为RxLifeCycle限制使用场景,在我们自定义View中很难应用自动解绑,而AutoDispose则可以解决这个问题,并且也提供了对应ViewScopeProvider,使用跟在Activity中一样,会自动在Detach时解绑。

MVP架构P层自动解绑

要完成P层自动解绑,需要了解几个类:LifecycleOwnerLifecycleLifecycleObserver,具体百度吧。
P层接口继承LifecycleObserver

public interface IPresenter extends LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreate(LifecycleOwner owner);

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(LifecycleOwner owner);
}

P层实现:

public class BasePresenter implements IPresenter {
    private LifecycleOwner mLifecycleOwner;

    @Override
    public void onCreate(LifecycleOwner owner) {
        this.mLifecycleOwner = owner;
    }

    protected <T> AutoDisposeConverter<T> bindLifecycle() {
        if (mLifecycleOwner == null) {
            throw new NullPointerException("未获取LifecycleOwner");
        }
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(mLifecycleOwner));
    }

    @Override
    public void onDestroy(LifecycleOwner owner) {
    }
}

最后在Activity或者Fragment注册订阅

public class Main2Activity extends AppCompatActivity {
    private BasePresenter mPresenter = new BasePresenter();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
       getLifecycle().addObserver(mPresenter);
}

完成三步,就可以实现P层生命周期监听以及自动解绑操作了。

结语

经过对比可看出AutoDispose在设计上更优于RxLifeCycle,无论是扩展性还是解耦上都比RxLifeCycle要强一些。而对于我们使用者来说,只要能够满足需求,就是好库。

下章预告:Rxjava解除订阅③:RxLife,敬请期待...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269