原文链接:http://nerds.weddingpartyapp.com/tech/2015/01/21/rxjava-share-publish-refcount-and-all-that-jazz/

看源码知道.share()操作符是.publish().refcount()调用链的包装。

先来看ConnectedObservable

“ConnectedObservable” – This is a kind of observable which doesn’t emit items even if subscribed to.
It only starts emitting items after its .connect() method is called.

因为这个原因,在ConnectedObservable的connect这个方法被调用之前,connected obesrvable也被认为是“冷”和不活跃。

再看publish方法

.publish()– This method allows us to change an ordinary observable into a “ConnectedObservable”.
Simply call this method on an ordinary observable and it becomes a connected one.

现在我们知道了share操作符的1/2,那么为什么需要运用Connected Observable这个操作符呢?文档上是这么写的:

In this way you can wait for all intended Subscribers to subscribe to the Observable before the Observable begins emitting items.

这就意味着publish可以调用多个subscriber。当你有超过一个订阅者的时候,处理每个订阅和正确的销毁他们变得棘手。 为了使这个更方便,Rx发明了这个魔法操作符refcount():

refcount() – This operator keeps track of how many subscribers are subscribed to the resulting Observable and
refrains from disconnecting from the source ConnectedObservable until all such Observables are unsubscribed.

refcount本质上在后台维护着一个引用计数器,当一个subscription需要取消订阅或者销毁的时候,发出一个正确的动作。

我们再次看一下debouncedBuffer的例子,看一下在哪,share是怎么用的。

Observable<Object> tapEventEmitter = _rxBus.toObserverable().share();
// which is really the same as:
Observable<Object> tapEventEmitter = _rxBus.toObserverable().publish().refcount();

我们现在有了一个"shareable"的名字叫"tapEventEmitter"的observable。 因为他是可以分享的,而且还不是“live”(share操作符中的publish调用使其变成一个ConnectedObservable), 我们可以用他构成我们的Observables,而且要确保我们有了一个原始的observable的引用 (这个例子中原始的observable是_rxBus.toObserverable()).

Observable<Object> tapEventEmitter = _rxBus.toObserverable().share();
Observable<Object> debouncedEventEmitter = tapEventEmitter.debounce(1, TimeUnit.SECONDS);
tapEventEmitter.buffer(debouncedEventEmitter)
//...

所有的这一切看起来都很好。然而这个实现会有一个可能的竞争条件。因为这有两个subscribers(debounce and buffer)而且会在不同的时间点发生,所以竞争条件就会发生。 记住RxBus是由hot/live Subject支持的不断的发射数据。通过使用share操作符,我们保证引用的是同一个资源。 而不是subscribers在不同的时间点订阅,他们会收到准确的相同的数据。

The race condition is when the two consumers subscribe. Often on a hot stream it doesn’t matter when subscribers come and go,and refCount is perfect for that.
The race condition refCount protects against is having only 1 active subscription upstream. However,if 2 Subscribers subscribe to a refcounted stream that emits 1, 2, 3, 4, 5, the first may get 1, 2, 3, 4, 5 and the second may get 2, 3, 4, 5. To ensure all subscribers start at exactly the same time and get the exact same values, refCount can not be used.
Either ConnectableObservable with a manual, imperative invocation of connect needs to be done, or the variant of publish(function)which connects everything within the function before connecting the upstream.

在我们的用法中几乎立即执行所以没有什么关系。但是我们原始的意图是把debouncedBuffer方法作为一个单独的操作符。 如果相同的事件没有被发射出去,从概念上看起来是不正确的。

通过Bean后来的建议,我添加了一个更好的第三方的实现,用来处理这种竞争条件。

// don't start emitting items just yet by turning the observable to a connected one
ConnectableObservable<Object> tapEventEmitter = _rxBus.toObserverable().publish(); tapEventEmitter.publish((Func1) (stream) -> { // inside `publish`, "stream" is truly multicasted // applying the same technique for getting a debounced buffer sequence
return stream.buffer(stream.debounce(1, TimeUnit.SECONDS)); }).subscribe((Action1) (taps) {
_showTapCount(taps.size());
}); // start listening to events now
tapEventEmitter.connect();

RxJava操作符之Share, Publish, Refcount的更多相关文章

  1. RxJava操作符(09-算术/聚合操作&连接操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51692493 本文出自:[openXu的博客] 目录: 算术聚合 Count Concat ...

  2. RxJava 操作符 on和doOn 线程切换 调度 Schedulers 线程池 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. RxJava操作符总结之过滤

    RxJava操作符总结之过滤 jsut() just(T t1, T t2, T t3 ....) ,just能够传入多个同样类型的參数,并将当前參数一个接着一个的发送. Observable.jus ...

  4. RxJava操作符实践:8_算术和聚合操作之3_min

    发射原始Observable的最小值. Min操作符操作一个发射数值的Observable并发射单个值:最小的那个值. RxJava中,min属于rxjava-math模块. min接受一个可选参数, ...

  5. RxJava操作符(08-条件和布尔操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51671826 本文出自:[openXu的博客] 目录: All Amb Contains D ...

  6. RxJava操作符(07-辅助操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51658445 本文出自:[openXu的博客] 目录: Delay Do Materiali ...

  7. RxJava操作符(06-错误处理)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51658235 本文出自:[openXu的博客] 目录: Catch Retry 源码下载 1 ...

  8. RxJava操作符(05-结合操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656736 本文出自:[openXu的博客] 目录: CombineLatest Join ...

  9. RxJava操作符(04-过滤操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656494 本文出自:[openXu的博客] 目录: Debounce Distinct ...

随机推荐

  1. codeforces 427E

    题意:给定一位空间里n个点的坐标,每个坐标有一个罪犯,现在要建一个警局,并且这个警局只有一辆车,车一次最多载m个人,问应建在哪是的抓回所有罪犯的路程和最小. 思路: 很明显建在罪犯的点上一定可以找到最 ...

  2. python numpy 介绍

    NumPy提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object).ndarray(下文统一称之 ...

  3. linux-4 虚拟机安装VMwareTOOls工具包

    第一步:在虚拟机中选择“安装.重新安装VMwareTools(T)” 第2步: 安装VMwareTools包 1.用root登录 2.   创建 /media/cdrom [root@localhos ...

  4. 移动App的REST API设计实践

    原文:http://www.jianshu.com/p/23cccb3a90b1 通讯协议 一些只是对服务器数据进行CRUD操作的App,通常采用HTTP协议,为了安全也可以采用HTTPS协议.IM软 ...

  5. [Microsoft Test Manager]CodeUI初探

      开发环境: Widnows8 Microsoft Visual Studio Ultimate 2012   1. 新建一个 Windows Forms Application Figue1 Cr ...

  6. 【shell脚本】显示文件的偶数或奇数行

    # Dispaly the odd line. awk 'NR%2==1' file

  7. [C++] 行程编码C++代码

    #include<iostream> #include<string.h> #include<string> #include<cstring> #in ...

  8. 深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants)

    访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类.类成员函数.类成员变量进行访问控制.同时,访问控制符也是语法保留关键字,用于封装组件. Public, Private, Protec ...

  9. 自旋锁-SpinLock(.NET 4.0+)

    短时间锁定的情况下,自旋锁(spinlock)更快.(因为自旋锁本质上不会让线程休眠,而是一直循环尝试对资源访问,直到可用.所以自旋锁线程被阻塞时,不进行线程上下文切换,而是空转等待.对于多核CPU而 ...

  10. C++ 关联容器

    <C++ Primer 4th>读书笔记 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. 关联容器(Ass ...