热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

rxlifecycle2原理分析

应用场景在这个RxJava已经火爆的不行的时代,如果你还没用那你就out了。用过RxJava的小伙伴都知道RxJava确实用的很爽,但是如果你处理的不好就会造成内存泄露,你可以自己

应用场景

在这个RxJava已经火爆的不行的时代,如果你还没用那你就out了。用过RxJava的小伙伴都知道RxJava确实用的很爽,但是如果你处理的不好就会造成内存泄露,你可以自己处理(在页面销毁的时候取消订阅),当然这样写起来是不是很麻烦,很不爽,这就让rxlifecycle有了存在的价值。

阅读本文之前需要对RxJava有简单的了解

使用方法

这个比较简单直接参考官方介绍即可 RxLifecycle

简单示例

Android开发直接添加这三个依赖就行了

compile 'com.trello.rxlifecycle2:rxlifecycle:2.2.0'
compile 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.0'
compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.0'

第三个可以不添加,在BaseActivity的生命周期里面自己绑定下就好了

1.指定生命周期断开(想在那断开就在那断开)

myObservable
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
.subscribe();

2.让RxLifecycle确定断开时机(省心是省心,一般不这么用)

myObservable
.compose(RxLifecycleAndroid.bindActivity(lifecycle))
.subscribe();

就是这么简单! 就是这么简单! 就是这么简单!

分析原理之前先讲几个RxJava的操作符帮助理解

1.Observable

  • compose 其实就是一个可以对Observable本身转变的一个操作
  • filter 可以理解为一个过滤满足条件的数据才发射出去
  • takeUntil 发射来自原始Observable的数据,直到第二个Observable发射了一个数据
    或一个通知。如果第二个Observable发射了一项数据或者发射了一个终止通知, 原始Observable会停止发射并终止。
  • CombineLatest 当两个Observables中的任何一个发射了数据时,使用一个函数结合每个Observable发射的最近数据项,并且基于这个函数的结果发射数据。
  • take 只发射前面的N项数据
  • skip 跳过前面的N项数据
  • share 简单来说就是让 Observable 支持多订阅

2.Observer

  • onNext 相当于让Observer接受一条新数据

下面简单介绍下Subject以及BehaviorSubject

1.Subject

Subject可以看成是一个桥梁或者代理,在RxJava中它同时充当了ObserverObservable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。

2.BehaviorSubject

BehaviorSubject继承自Subject,当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。rxlifecycle2中就是用的它!!!

都介绍完了就开始分析rxlifecycle2的实现原理了以绑定Activity的生命周期为例(重点来了准备好姿势)

先上一段简单代码

public abstract class RxActivity extends Activity implements LifecycleProvider {
private final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
@Override
@NonNull
@CheckResult
public final Observable lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final LifecycleTransformer bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
@CallSuper
protected void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}

首先RxActivity内部维护了个BehaviorSubject集Observable与Observer与一身,通过onNext()方法将Activity的各个生命周期与BehaviorSubject相结合,Activity每走一个生命周期BehaviorSubject就会接受到有个一个事件。

先来讲指定生命周期断开RxLifecycle.bindUntilEvent(lifecycle,ActivityEvent.DESTROY)

Observable
.compose(RxLifecycleAndroid.bindActivity(lifecycle))

当原始Observable调用compose方法的时候传入的就是RxLifecycleAndroid.bindActivity(lifecycle)
我们来看下他的源码

public static LifecycleTransformer bindUntilEvent(@Nonnull final Observable lifecycle,
@Nonnull final R event) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(event, "event == null");
return bind(takeUntilEvent(lifecycle, event));
}
private static Observable takeUntilEvent(final Observable lifecycle, final R event) {
return lifecycle.filter(new Predicate() {
@Override
public boolean test(R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(event);
}
});
}

先做了两个空判断然后执行一个过滤,过滤的条件就是lifecycleEvent.equals(event)只有这个条件满足的时候才发出数据这个条件是的意思相信你已经看懂了其实就是RxLifecycle.bindUntilEvent(lifecycleSubject, event);这个方法传的Observable也就是Activity里面维护的BehaviorSubject发出的事件和你指定销毁的事件相等的时候才成立BehaviorSubject才能把事件传递出去。

继续往下看bind(takeUntilEvent(lifecycle, event))

public static LifecycleTransformer bind(@Nonnull final Observable lifecycle) {
return new LifecycleTransformer<>(lifecycle);
}

其实就是new了个LifecycleTransformer并把lifecycle(也就是BehaviorSubject)通过构造方法传递进去了,最终把这个LifecycleTransformer一层层返回到原始Observable的compose方法中做参数。
我们在继续来看下这个LifecycleTransformer是什么

public final class LifecycleTransformer implements ObservableTransformer,
FlowableTransformer,
SingleTransformer,
MaybeTransformer,
CompletableTransformer
{
final Observable observable;
LifecycleTransformer(Observable observable) {
checkNotNull(observable, "observable == null");
this.observable = observable;
}
@Override
public ObservableSource apply(Observable upstream) {
return upstream.takeUntil(observable);
}
@Override
public Publisher apply(Flowable upstream) {
return upstream.takeUntil(observable.toFlowable(BackpressureStrategy.LATEST));
}
@Override
public SingleSource apply(Single upstream) {
return upstream.takeUntil(observable.firstOrError());
}
@Override
public MaybeSource apply(Maybe upstream) {
return upstream.takeUntil(observable.firstElement());
}
@Override
public CompletableSource apply(Completable upstream) {
return Completable.ambArray(upstream, observable.flatMapCompletable(Functions.CANCEL_COMPLETABLE));
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
LifecycleTransformer that = (LifecycleTransformer) o;
return observable.equals(that.observable);
}
@Override
public int hashCode() {
return observable.hashCode();
}
@Override
public String toString() {
return "LifecycleTransformer{" +
"observable=" + observable +
'}';
}
}

请看他实现了那些接口有没有看到ObservableTransformer,我们在回过头来看原始Observable的compose的源码

public final Observable compose(ObservableTransformer composer) {
return wrap(((ObservableTransformer) ObjectHelper.requireNonNull(composer, "composer is null")).apply(this));
}

发现没有compose最终执行的是ObservableTransformer的apply方法并把原始Observable通过参数传进去了,那实际上就是执行LifecycleTransformer的apply方法了,看看这个方法的实现

@Override
public ObservableSource apply(Observable upstream) {
return upstream.takeUntil(observable);
}

是不是恍然大悟,实际上就是执行upstream.takeUntil(observable),upstream就是原始的Observable而observable其实就是Activity里面维护的那个BehaviorSubject。

总结下就是原始的Observable通过takeUntil和BehaviorSubject绑定,当BehaviorSubject发出数据即Activity的生命周期走到和你指定销毁的事件一样时,原始的Observable就终止发射数据了

下面再来简单介绍下(RxLifecycleAndroid.bindActivity(lifecycle)原理差不多

来看下源码

// Figures out which corresponding next lifecycle event in which to unsubscribe, for Activities
private static final Function ACTIVITY_LIFECYCLE =
new Function() {
@Override
public ActivityEvent apply(ActivityEvent lastEvent) throws Exception {
switch (lastEvent) {
case CREATE:
return ActivityEvent.DESTROY;
case START:
return ActivityEvent.STOP;
case RESUME:
return ActivityEvent.PAUSE;
case PAUSE:
return ActivityEvent.STOP;
case STOP:
return ActivityEvent.DESTROY;
case DESTROY:
throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
public static LifecycleTransformer bindActivity(@NonNull final Observable lifecycle) {
return bind(lifecycle, ACTIVITY_LIFECYCLE);
}

bind方法传入的是lifecycle(BehaviorSubject)和 ACTIVITY_LIFECYCLE是一个Function
再看看bind源码

public static LifecycleTransformer bind(@Nonnull Observable lifecycle,
@Nonnull final Function correspondingEvents) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(correspondingEvents, "correspOndingEvents== null");
return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
}
private static Observable takeUntilCorrespondingEvent(final Observable lifecycle,
final Function correspondingEvents) {
return Observable.combineLatest(
lifecycle.take(1).map(correspondingEvents),
lifecycle.skip(1),
new BiFunction() {
@Override
public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(bindUntilEvent);
}
})
.onErrorReturn(Functions.RESUME_FUNCTION)
.filter(Functions.SHOULD_COMPLETE);
}

bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents))上面已经介绍过来这里就不在介绍了,重点就是LifecycleTransformer的apply方法执行upstream.takeUntil(observable)

ACTIVITY_LIFECYCLE 其实就是一个函数 Function ,把 Activity 的生命周期事件进行一下变换,CREATE 对应 DESTROY,RESUME 对应 PAUSE 等等。其含义就是 把当前的 Activity 生命周期转换成对应的需要被销毁的时候的生命周期。这个方法最终在lifecycle.take(1).map(correspondingEvents),中得到执行。而combineLatest方法就是把前面参数中的两个Observable基于第三个参数BiFunction整合后发射新的数据。lifecycleEvent.equals(bindUntilEvent)就是发射数据的条件。
lifecycle.take(1).map(correspondingEvents)相当指定销毁的的生命周期你在哪生命周期订阅的再参考ACTIVITY_LIFECYCLE 得到在要销毁的生命周期,最终还是和lifecycle(BehaviorSubject)发射的数据比较,如果两个一样说明Activity走到了该断开的生命周期了,upstream.takeUntil(observable)中的observable就要发通知告诉upstream(原始的Observable)该断开了。

本文參考
trello/RxLifecycle
BRUCEZZ&#8217;S CORNER
Rx中文文档


推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
author-avatar
钻探paz_106
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有