2016-06-06

  RxJava是最近两年火起来的一个框架,核心是异步,但是对于我来说印象最深的是响应式编程的思想。最近刚好想把自己的项目改成用RxJava实现,所以就研究了下。抛物线和大头鬼两位大牛也讲解的很详细和形象,其实RxJava里除了这种响应式的编程思想不太好理解外,操作符也是比较难理解的一部分。响应式编程思想不是三言两语就能讲清楚,想学习的人也不是通过看几遍blog就能学会的。我这里主要是讲操符,通过分解的方式一步一步带领大家看着到底是怎么回事,就以常用的map为例。

首先看一段伪代码:

Observable.create(new Observable.Onsubscrible(){  //------------ Observable one
@override
public object call(…subscriber){ //----------------------call one
……
subscriber.onNext(); //-------------- onNext one
…….
}
}).map(new Func1(){ // ----------------------map 操作后返回的为Observable two
@override
Public object call(…){ //-----------------------------call two
…….
} }).subscrible(new Subscriber(){
@override
public void onCompleted(){}
@override
Public void onError(){} @override
Public void onNext(){ //-------------------------onNext two
…….
}
});

我将剖析上面的一段RxJava代码。为了一步一步的把问题描述清楚,我们先把上面的代码简化如下,定义observableTemp变量:

observableTemp.subscrible(new Subscriber (){…..});

其中ObservableTemp为:

observableTemp =
observable.create(new Observable.Onsubscrible(){ //------------ Observable one
@override
public object call(…subscriber){ //----------------------call one
……
subscriber.onNext(); //-------------- onNext one
…….
}
}).map(new Func1(){ // ----------------------map 操作后返回的为Observable two
@override
Public object call(…){ //-----------------------------call two
…….
} });

   

第一步,我们先解析subscrible到底做了什么

  hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);

这是整个subscrible方法的核心。onSubscribeStart返回的是observable.onSubscribe,而observable.onSubscribe是传入参数,为this对象。所以可以把subcrible方法的主要功能简化为:

 ObservableTemp. onSubscribe.call(new Subscriber (){….});

举例说明下:如果

ObservableTemp =

Observable.create(new Observable.Onsubscrible(){

@override

public object call(…subscriber){  //---------------1-1

subscriber.onNext();

}

})

那么ObservableTemp. onSubscribe.call(new Subscriber (){….});分解如下:

ObservableTemp. onSubscrib = Observable.Onsubscrible()

这里的1-1传入值按照我们刚才简化后形式,应该是new Subscriber ()。那么整个就成了:

new Observable.Onsubscrible(){

@override

public object call(…subscriber){

……

subscriber.onNext();

……..

}

}.call(new Subscriber (){….});

这里的call就是调用的@override的call方法,所以这里进一步分解:

public object call(){

……

new Subscriber (){….}.onNext();

……..

}

看明白了吗?其实整个一大段代码只是执行了Subscriber里的onNext方法。

相信看到这里已经明白了subscribe方法的作用了。但是如果把ObservableTemp展开呢?也就是还原到开头的那段代码,又干了什么事情呢?请看第二步的分解

  

第二步,map到底做了什么

  我们已经知道ObservableTemp. onSubscribe.call(new Subscriber (){….});其实是通过ObservableTemp里的Onsubscrible.call方法直接调用Subscriber的onNext方法。那么加入map后,到底是怎么一种调用关系呢?Map字面的意思应该是个映射操作,那到底是不是字面上的映射?如果是映射,到底谁和谁之间的映射呢?

为了方便说明,我们还是把开头第一段代码做个简化,简化为:

ObservableTemp.map(new Func1(){…}).subcrible(new Subscriber(){…});

其中ObservableTemp 就是一个简单的对象创建和赋值过程了:

Observable.create(new Observable.Onsubscrible(){
@override
public object call(…subscriber){
……
subscriber.onNext();
…….
}
}); // 没有什么理解上的难度

map的操作代码是:

lift(new OperatorMap<T, R>(func));

lift是RxJava里核心,几乎大部分Observable操作都是需要用到lift方法。A.lift(Operator op)返回的是一个新的Observable,新Observable中的OnSubscribe为OnSubscribeLift。

ObservableTemp.map(new Func1(){…}).subcrible(new Subscriber(){…});

就变成了:

new Observable(new OnSubscribeLift(){
@override
Public object call(…){
…….
}
}).subcrible(new Subscriber(){…}); // ------------------------- 2-2

是不是很眼熟,Yes, 就是第一步里简化的步骤。那么这里关键的部分来了,OnSubscribeLift里的call做了什么,如果我们把这个搞清楚了,那么map就自然而然的就清楚了。

OnSubscribeLift里的call主要有两行代码:

Subscriber<? super T> st = hook.onLift(operator).call(o);
parent.call(st);

这里的operator,o ,parent以及 st到底是什么呢?

因为这里的o是OnSubscribeLift里call方法传入的参数,由2-2可以知道,o其实代表的是new Subscriber()。

再看operator,由代码可以看出:

public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return lift(new OperatorMap<T, R>(func));
}

这里的operator就是指经过OperatorMap包装过的Operator对象:new OperatorMap<T, R>(new Func1());而hook.onLift(operator)返回的就是operator,那么上面两句代码可以看成:

Subscriber<? super T> st = (new OperatorMap<T, R>(new Func1())).call(o);
parent.call(st);

OperatorMap里的call做了三件事情:

MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
o.add(parent);
return parent;

把 new subscriber()和new Func1()(就是transformer对象)通过MapSubscriber封装起来。然后新的Subcriber(MapSubscriber对象)放入订阅列表中,以便最后一起把订阅对象释放。同时返回新的Subcriber。

根据上述的,

Subscriber<? super T> st = (new OperatorMap<T, R>(new Func1())).call(o);
parent.call(st);

可以看成:

Subscriber<? super T> st  = new MapSubscriber<T, R>(o, transformer);
parent.call(st);

而parent是传入的参数,指ObservableTemp.onSubscribe,也就是开头代码中的Observable one。

进一步上述两行代码可以看成:

Subscriber<? super T> st  = new MapSubscriber<T, R>(o, transformer);
(new Observable.Onsubscrible(){ //------------ Observable one
@override
public object call(…subscriber){ //----------------------call one
……
subscriber.onNext(); //-------------- onNext one
…….
}
}).call(st);

这里的override里的call参数为new MapSubscriber<T, R>(o, transformer); new MapSubscriber<T, R>(o, transformer).onNext主要代码为:

@Override
public void onNext(T t) {
result = mapper.call(t);
actual.onNext(result);
}

Mapper就是transformer对象,也就是new Func1(),而actual就是new subscriber()。也就是说:把Observable one里的类型经过new Func1().call的方法转换成另外一个Subscriber,最后调用new Subscriber的onNext方法。

所以map整个过程就清楚了:
A.map(B).subscribe(C) 就是:

先通过map方法,把A中想要转换的数据通过调用B里的call方法进行转换,最后把转换过的数据用C里的onNext方法进行处理。

我们抛开onCompleted和onError方法,

A.map(B).subscribe(C)  <==> 
C.onNext (B.call(A.onNext()))

RxJava Map操作详解的更多相关文章

  1. GoLang基础数据类型--->字典(map)详解

    GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...

  2. C++中的STL中map用法详解(转)

    原文地址: https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html C++中的STL中map用法详解   Map是STL的一个关联容器,它提供 ...

  3. MongoDB各种查询操作详解

    这篇文章主要介绍了MongoDB各种查询操作详解,包括比较查询.关联查询.数组查询等,需要的朋友可以参考下   一.find操作 MongoDB中使用find来进行查询,通过指定find的第一个参数可 ...

  4. Linux Shell数组常用操作详解

    Linux Shell数组常用操作详解 1数组定义: declare -a 数组名 数组名=(元素1 元素2 元素3 ) declare -a array array=( ) 数组用小括号括起,数组元 ...

  5. [Android新手区] SQLite 操作详解--SQL语法

    该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解 ...

  6. shell字符串操作详解

    shell字符串操作详解的相关资料. 1.shell变量声明的判断  表达式 含义 ${var} 变量var的值, 与$var相同 ${var-DEFAULT} 如果var没有被声明, 那么就以$DE ...

  7. memcached 命令操作详解

    memcached 命令操作详解 一.存储命令 存储命令的格式: <command name> <key> <flags> <exptime> < ...

  8. windows phone 8.1开发SQlite数据库操作详解

    原文出自:http://www.bcmeng.com/windows-phone-sqlite1/ 本文小梦将和大家分享WP8.1中SQlite数据库的基本操作:(最后有整个示例的源码)(希望能通过本 ...

  9. MySQL 操作详解

    MySQL 操作详解 一.实验简介 本节实验中学习并实践 MySQL 上创建数据库.创建表.查找信息等详细的语法及参数使用方法. 二.创建并使用数据库 1. 创建并选择数据库 使用SHOW语句找出服务 ...

随机推荐

  1. 模仿qq界面实现(WTL)

    前面对于界面用哪一种我试过用duilib,但是老感觉和MFC差距有点多,终于发现WTL的库能够实现我的所有界面功能,几天的努力终于搞定界面的重写.还是见我的成果吧: 1登录界面: 2主界面: 3.主界 ...

  2. JS如何实现点击页面其他地方隐藏菜单?

    方法一: $("#a").on("click", function(e){  $("#menu").show();    $(documen ...

  3. 我的Java笔记

    第一章 一 计算机程序:一系列有序的指令集合. 二 java语言分为三个领域 javaSE java技术核心(桌面应用程序)qq 百度云 javaEE 企业版(面向internet的应用程序)京东 淘 ...

  4. 源码(03) -- java.util.Collection<E>

     java.util.Collection<E> 源码分析(JDK1.7) -------------------------------------------------------- ...

  5. 使用Hugo搭建GitHub个人博客

    主题概况 Hugo 是一个用 Go 语言编写的静态网站生成器.类似的静态网站生成器还有Jekyll.hexo等等.以上生成器都使用过,但感觉要么环境麻烦,要么生成静态页面步骤繁琐以及生成缓慢.如果你正 ...

  6. C++ 头文件系列(sstream)

    1. 简介 这个头文件主要定义了基于字符串类(string类)的流的4个模版: basic_stringbuf basic_istringstream basic_ostringstream basi ...

  7. 转载 JDK + Android-SDK + Python + MonkeyRunner 的安装

    转载来自: 小海豚的博客   http://blog.sina.com.cn/u/1295334083 我只是搬运工... JDK + Android-SDK + Python + MonkeyRun ...

  8. 基于微博数据用 Python 打造一颗“心”

    一年一度的虐狗节刚过去不久,朋友圈各种晒,晒自拍,晒娃,晒美食,秀恩爱的.程序员在晒什么,程序员在加班.但是礼物还是少不了的,送什么好?作为程序员,我准备了一份特别的礼物,用以往发的微博数据打造一颗“ ...

  9. ES(二): Build ES Cluster on Azure VM

    目录: 系统环境准备 安装ES集群 安装Kibana 安装x-pack 安装head 系统环境准备 参见: HDP2.4安装(二):Centos7配置 修改network: 修改hosts: 配置ss ...

  10. 纪中集训 Day 6

    今天他们回去了,就剩我和DWJ(一位初三大大(后来问云神才知道的ORZ))一起在做题,不得不说他真的是太厉害了,一个升初三大大在各种方面都比我强QAQ 让我突然感觉到自己的高一还是不够努力啊QAQ 连 ...