欢迎转载,转载请标明出处:

http://blog.csdn.net/johnny901114/article/details/51524470

本文出自:【余志强的博客】

1 create操作符的基本使用

顾名思义,Create操作符是用来创建一个Observable的。下面来看一个简单的代码段:

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            //Emit Data
        }
})

create方法接收一个参数Observable.OnSubscribe 来看下它的源码:

    /**
     * Invoked when Observable.subscribe is called.
     */
    public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
        // cover for generics insanity
    }

Observable.OnSubscribe 说白了就是一个继承了Action1接口的接口:

public interface Action1<T> extends Action {
    void call(T t);
}
/**
 * All Action interfaces extend from this.
 * <p>
 * Marker interface to allow instanceof checks.
 */
public interface Action extends Function {

}
/**
 * All Func and Action interfaces extend from this.
 * <p>
 * Marker interface to allow instanceof checks.
 */
public interface Function {

}

它们的继承关系如下:

Observable.OnSubscribe <- Action1 <- Action <- Function

create()方法也就是个工厂方法:

public static <T> Observable<T> create(OnSubscribe<T> f) {
    return new Observable<T>(hook.onCreate(f));
}

通过OnSubscribe的源码的注释

Invoked when Observable.subscribe is called. 意思是 当Observable被订阅(subscribe)

OnSubscribe接口的call方法会被执行。

知道如何创建(create)Observable, 接下来我们看下如何订阅它:

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        for (int i = 0; i < 5; i++) {
            printLog(tvLogs, "Emit Data:", i + "");
            subscriber.onNext("" + i);
        }
    }
})
.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        //showToast(s);
        printLog(tvLogs, "Consume Data:", s);
    }
});

当调用了subscribe方法 Observable.OnSubscribe的call方法就会被执行,在Observable.OnSubscribe的call方法中循环了调用了5次subscriber.onNext,在subscribe的Action1回调就会接受5次回调。

Emit Data:'0' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'1' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'2' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'3' , Thread Name:RxCachedThreadScheduler-1
Emit Data:'4' , Thread Name:RxCachedThreadScheduler-1
Consume Data:'0' , Thread Name:main
Consume Data:'1' , Thread Name:main
Consume Data:'2' , Thread Name:main
Consume Data:'3' , Thread Name:main
Consume Data:'4' , Thread Name:main

从输出的日志可以看到,我们还打印了Thread Name线程的名称,我们可以控制发送数据、消费数据所在的线程。

.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())

subscribeOn 设置Observable的call方法所在的线程 【生产数据】

observeOn 设置subscribe的call方法所在的线程【消费数据】

2 从源码角度分析create()和subscribe()如何协同工作的

从上面的分析我们知道,create方法就是一个简单的工厂方法:

public static <T> Observable<T> create(OnSubscribe<T> f) {
    return new Observable<T>(hook.onCreate(f));
}

直接new一个Observable 接收的参数由hook.onCreate方法返回(该方法也很简单):

public <T> OnSubscribe<T> onCreate(OnSubscribe<T> f) {
    return f;
}
protected Observable(OnSubscribe<T> f) {
    this.onSubscribe = f;
}

总结下来一句话:create操作符创建Observable,Observable通过构造方法 保存了我们传进来的OnSubscribe 说白了就是Action1.

下面来看看Observable的subscribe方法的源代码:

public final Subscription subscribe(final Action1<? super T> onNext) {
        if (onNext == null) {
            throw new IllegalArgumentException("onNext can not be null");
        }
        return subscribe(new Subscriber<T>() {

            @Override
            public final void onCompleted() {
                // do nothing
            }

            @Override
            public final void onError(Throwable e) {
                throw new OnErrorNotImplementedException(e);
            }

            @Override
            public final void onNext(T args) {
                onNext.call(args);
            }
        });
    }

从源码可以看出subscribe方法并没有直接调用传进来参数的方法(没有直接调用onNext.call())。

而是通过subscribe(Subscriber)方法, subscribe(Subscriber)方法又是调用了Observable的私有静态方法:private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) 。下面是该方法的源码片段:

private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {

        //remove some code ....

        try {
            // allow the hook to intercept and/or decorate
            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
            return hook.onSubscribeReturn(subscriber);
        } catch (Throwable e) {
            // special handling for certain Throwable/Error/Exception types
            Exceptions.throwIfFatal(e);
            // if an unhandled error occurs executing the onSubscribe we will propagate it
            try {
                subscriber.onError(hook.onSubscribeError(e));
            } catch (Throwable e2) {
                Exceptions.throwIfFatal(e2);
                // if this happens it means the onError itself failed (perhaps an invalid function implementation)
                // so we are unable to propagate the error correctly and will just throw
                RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
                // TODO could the hook be the cause of the error in the on error handling.
                hook.onSubscribeError(r);
                // TODO why aren't we throwing the hook's return value.
                throw r;
            }
            return Subscriptions.unsubscribed();
        }
    }

我们看关键部分就可以了:hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);

看看hook.onSubscribeStart源码:

  public <T> OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance, final OnSubscribe<T> onSubscribe) {
      // pass-thru by default
      return onSubscribe;
  }

很简单,直接返回传递过来的参数(onSubscribe)。 这个OnSubscribe就是我们Observable.create(OnSubscribe)传递进去的OnSubscribe,然后调用OnSubscribe的call。

所以上面的代码可以简化为(便于理解):observable.onSubscribe.call(subscriber).

至此,验证了那句话,只有当Observable被订阅OnSubscribe的call(subscriber)方法才会被执行。

我们知道了OnSubscribe的call(subscriber)执行的时机,那么是如何把生产的数据传递了Observable.subscribe方法的回调的呢?

我们通过Observable.subscribe源码得知,传递进来的回调(Action1),是通过Subscriber来执行Action1的回调,Subscriber又是Observable.create()参数的回调。

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            //Emit Data
        }
})

所以Subscriber是Observable.OnSubscribe的回调和Observable.subscribe(Action1..)的Action1之间通信的桥梁。

Subscriber有三个方法:

  • onCompleted();
  • void onError(Throwable e);
  • void onNext(T t);

既然Subscriber是Observable.create(params)参数的回调和Observable.subscribe()参数回调的通信桥梁,Subscriber有三个方法,那么Observable.subscribe肯定也有三个与之对应回调,通过源码知道Observable.subscribe有很多重载方法:

  • public final Subscription subscribe(final Action1
总结:Subscriber是Observable.create(Observable.OnSubscribe)参数回调和Observable.subscribe(Action1,[Action1,Action0])参数回调的通信桥梁.

需要你注意的是:如果调用了void onError(Throwable e)方法,那么onNext和onCompleted都不会执行。

下面用代码来表示他们之间的关系:

Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            for (int i = 0; i < 5; i++) {
                printLog(tvLogs, "Emit Data:", i + "");
                subscriber.onNext("" + i);//对应subscribe方法的第一个参数
                if (condition) {
                    subscriber.onError(Throwable);//对应subscribe方法的第二个参数
                }
            }
            subscriber.onCompleted(); //对应subscribe方法的第三个参数
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            //showToast(s);
            printLog(tvLogs, "Consume Data:", s);
            //onNext
        }
    }, new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            //onError
        }
    }, new Action0() {
        @Override
        public void call() {
            //onCompleted
        }
    });
总结:
1. 只有当Observable被订阅OnSubscribe的call(subscriber)方法才会被执行
2. 如果调用了void onError(Throwable e)方法,那么onNext和onCompleted都不会执行
3. Subscriber是Observable.create(Observable.OnSubscribe)参数回调和Observable.subscribe(Action1,[Action1,Action0])参数回调的通信桥梁.

github源码下载

RxJava(一) create操作符的用法和源码分析的更多相关文章

  1. LinearLayout属性用法和源码分析

    转载自:http://www.jianshu.com/p/650c3fd7e6ab   一. LinearLayout的属性和用法 LinearLayout对于开发来说,是使用最常用的布局控件之一,但 ...

  2. 一文搞懂 CountDownLatch 用法和源码!

    CountDownLatch 是多线程控制的一种工具,它被称为 门阀. 计数器或者 闭锁.这个工具经常用来用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用).下面我们就来一起 ...

  3. jQuery静态方法globalEval使用和源码分析

    Eval函数大家都很熟悉,但是globalEval方法却很少使用,大多数参考手册也没有相关api,下面就对其用法和源码相应介绍: jQuery.globalEval()函数用于全局性地执行一段Java ...

  4. Android Debuggerd 简要介绍和源码分析(转载)

    转载: http://dylangao.com/2014/05/16/android-debuggerd-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%92%8C%E ...

  5. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...

  6. Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...

  7. Kubernetes Job Controller 原理和源码分析(一)

    概述什么是 JobJob 入门示例Job 的 specPod Template并发问题其他属性 概述 Job 是主要的 Kubernetes 原生 Workload 资源之一,是在 Kubernete ...

  8. Kubernetes Job Controller 原理和源码分析(二)

    概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...

  9. Kubernetes Job Controller 原理和源码分析(三)

    概述Job controller 的启动processNextWorkItem()核心调谐逻辑入口 - syncJob()Pod 数量管理 - manageJob()小结 概述 源码版本:kubern ...

随机推荐

  1. 【Swfit】Swift与OC两种语法写单例的区别

    Swift与OC两种语法写单例的区别 例如写一个NetworkTools的单例 (1)OC写单例 + (instancetype)sharedNetworkTools { static id inst ...

  2. Mysql之表的操作与索引操作

    表的操作: 1.表的创建: create table if not exists table_name(字段定义); 例子: create table if not exists user(id in ...

  3. chall.tasteless.eu 中的注入题

    第一题好像就很难,看了payload,算是涨见识了,感觉有点为了猜而猜. 题目给我们的时候是这样的:http://chall.tasteless.eu/level1/index.php?dir=ASC ...

  4. Struts支持的contentType

    'ez' => 'application/andrew-inset', 'hqx' => 'application/mac-binhex40', 'cpt' => 'applicat ...

  5. 【bzoj4572 scoi2016】围棋

    题目描述 近日,谷歌研发的围棋AI—AlphaGo以4:1的比分战胜了曾经的世界冠军李世石,这是人工智能领域的又一里程碑. 与传统的搜索式AI不同,AlphaGo使用了最近十分流行的卷积神经网络模型. ...

  6. hdu 5538(水)

    Input The first line contains an integer T indicating the total number of test cases. First line of ...

  7. Hash算法入门指南(聊点不一样的算法人生)

    前言 很多人到现在为止都总是问我算法该怎么学啊,数据结构好难啊怎么的,学习难度被莫名的夸大了,其实不然.对于一个学计算机相关专业的人都知道,数据结构是大学的一门必修课,数据结构与算法是基础,却常常容易 ...

  8. 以太坊MetaMask钱包插件简介

    MetaMask是一个以太坊钱包插件,虽然只能在Chrome浏览器中使用,但作为以太坊钱包的metamask却很受以太坊开发者欢迎. MetaMask 评价(5★):安装设置:★★★★界面操作:★★★ ...

  9. Python中内置函数的介绍

    内置函数的功能介绍 常用内置函数如下: 1.abs() 绝对值 格式:abs(x) 例如:print(abs(-18)) >>> 18 返回值:number #该函数主要用于数值类的 ...

  10. Linux允许、禁止ping包

    默认情况下Linux系统允许ping,但是在某些情况下为了安全起见,我们都把服务器设置为禁ping  临时允许ping命令可使用命令: echo 0 >/proc/sys/net/ipv4/ic ...