1.结构

Rxlifecycle代码很少,也很好理解,来看核心类。

  • 接口ActivityLifecycleProvider

    RxFragmentActivity、RxAppCompatActivity、RxFragment等类所有的组件类皆实现这个借口

  • 类RxLifecycle

2.详细分析

以RxAppCompatActivity入手来分析。

  1. 初始化一个BehaviorSubject,Subject因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。Subject的详细介绍:https://mcxiaoke.gitbooks.io/rxdocs/content/Subject.html

    private final BehaviorSubject<ActivityEvent>
    lifecycleSubject = BehaviorSubject.create();
  2. 在activity每个生命的周期Subject发射相对应的事件。

    @Override
    @CallSuper
    protected void onStart() {
    super.onStart();
    //发送start事件
    lifecycleSubject.onNext(ActivityEvent.START);
    }
    ....

分析RxLifecycle核心的方法:bindUntilActivityEvent

  1. bindUntilActivityEvent也就是调用的bindUntilEvent

    private static <T, R> Observable.Transformer<T, T> bindUntilEvent(final Observable<R> lifecycle,
    //返回 Transformer final R event) {
    return new Observable.Transformer<T, T>() {
    @Override
    public Observable<T> call(Observable<T> source) {
    return source.takeUntil(
    lifecycle.takeFirst(new Func1<R, Boolean>() {
    @Override
    public Boolean call(R lifecycleEvent) {
    return lifecycleEvent == event;
    }
    })
    );
    }
    };
    }

这个方法接收两个参数,lifecycle就是activity里面的BehaviorSubject对象,event就是要我们设置的要在activity哪个生命周期取消订阅的ActivityEvent对象。

返回参数是Transformer,用来结合compose使用 Transformer相当于一个过滤器,Observable call(Observable source) 接收一个Observable然后经过处理再返回一个Observable

这个方法从里到外一层一层剥开:

lifecycle.takeFirst(new Func1<R, Boolean>() {
@Override
public Boolean call(R lifecycleEvent) {
return lifecycleEvent == event;
}
})

如果lifecycleEvent == event结果为true,lifecycle既BehaviorSubject对象发射一个数据。

lifecycleEvent是BehaviorSubject发射的数据,既ActivityEvent对象,比如在onStart时候lifecycleSubject.onNext(ActivityEvent.START)发送的ActivityEvent.START。 event是传递进来的参数。

接着上看

return source.takeUntil()

lifecycle最核心的就是这个takeUntil。

source就是要调用compose的原始的Observable,就是例子中这个Observable

  Observable.interval(1, TimeUnit.SECONDS)
.compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE))
...

来看takeUntil

Returns an Observable that emits the items emitted by the source Observable until a second Observable emits an item.

如果lifecycle.takeFirst发射了一条数据,takeUntil就回触发,source Observable就回停止发射数据,执行Unsubscribe,流自动结束。

分析RxLifecycle核心的方法:bindUntilActivityEvent

上代码

private static <T, R> Observable.Transformer<T, T> bind(Observable<R> lifecycle,
final Func1<R, R> correspondingEvents) {
...
// Make sure we're truly comparing a single stream to itself
final Observable<R> sharedLifecycle = lifecycle.share(); // Keep emitting from source until the corresponding event occurs in the lifecycle
return new Observable.Transformer<T, T>() {
@Override
public Observable<T> call(Observable<T> source) {
return source.takeUntil(
Observable.combineLatest(
sharedLifecycle.take(1).map(correspondingEvents),
sharedLifecycle.skip(1),
new Func2<R, R, Boolean>() {
@Override
public Boolean call(R bindUntilEvent, R lifecycleEvent) {
return lifecycleEvent == bindUntilEvent;
}
})
.onErrorReturn(RESUME_FUNCTION)
.takeFirst(SHOULD_COMPLETE)
);
}
};
}
  1. .share()操作符:
  2. 来看Observable.combineLatest,这个操作符接收三个参数。

    第一个参数:取BehaviorSubject发射的数据中的第一个,然后转换成对应的生命周期。例如在onStart()中调用了bindToLifecycle,take(1)后的数据是ActivityEvent.START,经过map(),返回ActivityEvent.STOP。

    第二个参数:从BehaviorSubject发射的数据中经过.skip(1)操作符,过滤掉第一个数据。例如在onStart()中调用了bindToLifecycle,在后续的生命周期中会收到,ActivityEvent.RESUME、ActivityEvent.PAUSE、ActivityEvent.STOP、ActivityEvent.DESTROY

    第三个参数:作用是combineFunction,把前两个参数最近发射的数据按照规则进行合并。规则是比对两次事件是否相等,然后合并后数据返回Boolean结果。比如params2发射ActivityEvent.RESUME的时候,和params1发射的ActivityEvent.STOP进行比对,返回false结果;params2发射ActivityEvent.STOP的时候,和params1发射的ActivityEvent.STOP进行比对,返回true结果。

  3. onErrorReturn()

    private static final Func1<Throwable, Boolean> RESUME_FUNCTION = new Func1<Throwable, Boolean>() {
    @Override
    public Boolean call(Throwable throwable) {
    if (throwable instanceof OutsideLifecycleException) {
    return true;
    } Exceptions.propagate(throwable);
    return false;
    }
    };

    如果发生错误,判断是否是自定义错误类型 OutsideLifecycleException,如果是,则返回true,否则其他错误类型返回false。

  4. .takeFirst(SHOULD_COMPLETE)

    private static final Func1<Boolean, Boolean> SHOULD_COMPLETE = new Func1<Boolean, Boolean>() {
    @Override
    public Boolean call(Boolean shouldComplete) {
    return shouldComplete;
    }
    };

    返回第一个结果是true的数据。如果combineLatest链中返回false,则不发射任何数据。

  5. source.takeUntil

    如果combineLatest.onErrorReturn.takeFirst链返回true,则takeUntil操作符终止订阅,source Observable就回停止发射数据,执行Unsubscribe,流自动结束。

OVER!

Rxlifecycle(二):源码解析的更多相关文章

  1. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  2. Cwinux源码解析(二)

    我在我的个人博客上发表了第二篇解析文章.欢迎各位读者批评指正. Cwinux源码解析(二)

  3. 【vuejs深入三】vue源码解析之二 htmlParse解析器的实现

    写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 昨天博主分析了一下在vue中,最为基础核心的api,parse函数,它的作用是将vue的模板字符串转换成ast,从而 ...

  4. [java源码解析]对HashMap源码的分析(二)

    上文我们讲了HashMap那骚骚的逻辑结构,这一篇我们来吹吹它的实现思想,也就是算法层面.有兴趣看下或者回顾上一篇HashMap逻辑层面的,可以看下HashMap源码解析(一).使用了哈希表得“拉链法 ...

  5. Java源码解析——集合框架(二)——ArrayBlockingQueue

    ArrayBlockingQueue源码解析 ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection ...

  6. # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#

    Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...

  7. Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码

    在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...

  8. Spring事务源码解析(二)获取增强

    在上一篇文章@EnableTransactionManagement注解解析中,我们搭建了源码阅读的环境,以及解析了开启Spring事务功能的注解@EnableTransactionManagemen ...

  9. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  10. iOS即时通讯之CocoaAsyncSocket源码解析二

    原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查:本机地 ...

随机推荐

  1. 【整理】--VC 编译整理

    .h用于编译阶段的审核,如在math.h中有函数声明:int abs(int);但是在使用中写为#include <math.h>...abs(3,5);编译器阶段就会检测出错误. .dl ...

  2. C++混合编程之idlcpp教程Lua篇(4)

    上一篇在这  C++混合编程之idlcpp教程Lua篇(3) 与前面的工程相似,工程LuaTutorial2中,同样加入了三个文件 LuaTutorial2.cpp, Tutorial2.i, tut ...

  3. Nginx提示502和504错误的解决方案

    一.错误提示说明: Nginx 502 Bad Gateway的含义是请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致PHP-CGI进程终止. Nginx 50 ...

  4. Android 5.x特性概览一

    2014年,Google 携 Android 5.X 重装回归.迄今为止已有已有两年有余,全新设计的 UI风格和更加强悍的性能,再一次奠定了Android 的霸主地位.本文将就 UI 方面 Googl ...

  5. [Xamarin] 透過 intent-filter 來接管 http ,製作偽瀏覽器 (转帖)

    使用Android 的朋友一定對這畫面不陌生在開啟網址的時候,或是Youtube連結的時候,因為Android 發現,你手機安裝的App有哪些可以支援這些東西的瀏覽 所以,就可以使用甚麼東西來進行開啟 ...

  6. (转载)Autodesk面试技术题解答

    Autodesk面试技术题解答 By SmartPtr(http://www.cppblog.com/SmartPtr/)          近一年以来,AUTODESK的面试题在网上是闹的沸沸扬扬, ...

  7. 在服务器端将现有Git项目导入GitLab

    GitLab是由Ruby语言开发的基于Linux的Git服务器,是我见过的最强大的Git服务器.发现它之后,立即决定将Git服务器换成GitLab. 但安装好GitLab之后面临一个问题,如何将服务器 ...

  8. 高手速成android开源项目【导航篇】

    Android开发又将带来新一轮热潮,很多开发者都投入到这个浪潮中去了,创造了许许多多相当优秀的应用.其中也有许许多多的开发者提供了应用开源项目,贡献出他们的智慧和创造力.学习开源代码是掌握技术的一个 ...

  9. 【Android Studio】Android Studio 安装及设置

    版权所有, 禁止转载, 如有需要, 请站内联系. 本文地址: http://blog.csdn.net/caroline_wendy/article/details/20845807 时间: 2014 ...

  10. iOS开发-迭代器模式

    迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示.开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望 ...