Rxlifecycle(二):源码解析
1.结构
Rxlifecycle代码很少,也很好理解,来看核心类。
接口ActivityLifecycleProvider
RxFragmentActivity、RxAppCompatActivity、RxFragment等类所有的组件类皆实现这个借口
类RxLifecycle
2.详细分析
以RxAppCompatActivity入手来分析。
初始化一个BehaviorSubject,Subject因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。Subject的详细介绍:https://mcxiaoke.gitbooks.io/rxdocs/content/Subject.html
private final BehaviorSubject<ActivityEvent>
lifecycleSubject = BehaviorSubject.create();在activity每个生命的周期Subject发射相对应的事件。
@Override
@CallSuper
protected void onStart() {
super.onStart();
//发送start事件
lifecycleSubject.onNext(ActivityEvent.START);
}
....
分析RxLifecycle核心的方法:bindUntilActivityEvent
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)
);
}
};
}
- .share()操作符:
来看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结果。
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。
.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,则不发射任何数据。
source.takeUntil
如果combineLatest.onErrorReturn.takeFirst链返回true,则takeUntil操作符终止订阅,source Observable就回停止发射数据,执行Unsubscribe,流自动结束。
OVER!
Rxlifecycle(二):源码解析的更多相关文章
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- Cwinux源码解析(二)
我在我的个人博客上发表了第二篇解析文章.欢迎各位读者批评指正. Cwinux源码解析(二)
- 【vuejs深入三】vue源码解析之二 htmlParse解析器的实现
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 昨天博主分析了一下在vue中,最为基础核心的api,parse函数,它的作用是将vue的模板字符串转换成ast,从而 ...
- [java源码解析]对HashMap源码的分析(二)
上文我们讲了HashMap那骚骚的逻辑结构,这一篇我们来吹吹它的实现思想,也就是算法层面.有兴趣看下或者回顾上一篇HashMap逻辑层面的,可以看下HashMap源码解析(一).使用了哈希表得“拉链法 ...
- Java源码解析——集合框架(二)——ArrayBlockingQueue
ArrayBlockingQueue源码解析 ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection ...
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码
在文章:Mybatis源码解析,一步一步从浅入深(一):创建准备工程,中我们为了解析mybatis源码创建了一个mybatis的简单工程(源码已上传github,链接在文章末尾),并实现了一个查询功能 ...
- Spring事务源码解析(二)获取增强
在上一篇文章@EnableTransactionManagement注解解析中,我们搭建了源码阅读的环境,以及解析了开启Spring事务功能的注解@EnableTransactionManagemen ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- iOS即时通讯之CocoaAsyncSocket源码解析二
原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查:本机地 ...
随机推荐
- hdu 4651 - Partition(五边形数定理)
定理详见维基百科....http://zh.wikipedia.org/wiki/%E4%BA%94%E9%82%8A%E5%BD%A2%E6%95%B8%E5%AE%9A%E7%90%86 代码如下 ...
- C/C++中static关键字详解
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...
- Linux分区,并且把新的分区挂载到指定的文件夹
本教程为在已使用的Linux系统中新加入一个硬盘. 1.fdisk –l 查看:看到新加入硬盘hdd 2.输入:fdisk /dev/hdd 3.键入m查看有哪些命令: 4.键入p查看一下硬盘hdd的 ...
- [ASE][Daily Scrum]11.17
这两天感冒了没有第一时间更新blog和tfs,给大家抱歉了! 上周五我们已经将服务器搭建完成并成功通讯,周六周日大家非常给力的完成了很多内容! View Shilin Liu 处理来自服务器的数据 显 ...
- property和attribute的区别
property是指类向外提供的数据区域.而attribute则是描述对象在编译时或运行时属性的,分为固有型和用户自定义型,其中用户自定义型可以利用Reflection在运行期获取.这两者是有本质区别 ...
- Bug Tracker 使用笔记(有图有真相)
目的:管理Bug,完善业务流程. 前提条件:BugTracker是基于IIS和SQL Server和Asp.Net的.相当于一个Web端的管理系统. 1.下载地址 http://sourceforge ...
- 架构模式对象与关系结构模式之:标识域(Identity Field)
一:标识域(Identity Field) 标识域(Identity Field)可以理解为主键.使用领域模型和行数据入口的时候,就要使用标识域,因为这两个对象代表的是唯一存在的那个数据记录.事务脚本 ...
- [C++] socket - 3 [线程简单例子 代码]
#include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数 D ...
- .net中对象序列化技术浅谈
.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储 ...
- Atitit.人力资源管理原理与概论
Atitit.人力资源管理原理与概论 1. 人力资源管理 第一章 人力资源管理概述 第二章 人力资源理论基础与发展演变 第三章 人力资源规划 第四章工作分析与工作设计 第五章 员工招聘与录用 第六章 ...