Rxjava中的ConnectableObservable

来源:互联网 发布:申请哥伦比亚大学知乎 编辑:程序博客网 时间:2024/04/29 17:40

ConnectableObservable

ConnectableObserable继承自Observable,具备Observable功能。

特点: (特别注意第2点)

1. ConnectableObservable数据并不是当观察者订阅时就发送数据,只   调用了connect()方法,才开始发送数据。2. ConnectableObservable线程切换比较特别。通过"replay"操   作符实现,而且它的"订阅"和"观察"是在同相同线程。传统的   subscribeOn()和observerOn(),不起作用,如果不通过replay指   定线程,那么它的工作线程有调用线程决定。   关于线程切换,文章后面会有用法和验证

获取ConnectableObservable实例的两种方式

publish操作符

Observable通过pulish操作符获取的ConnectableObservable和PublisSubject(对PublisSubject还不熟悉的,可以看我上一篇文章Rxjava2.0中的Subject)功能基本一样,唯一区别就是,ConnectableObservable调用connect之后才开始发射数据。

ConnectableObservable<String> connect = Observable.just("1","2","3","4","5","6").publish() ;        connect.subscribe(getObserver("pob1:")) ;        connect.connect() ;        connect.subscribe(getObserver("pob2:")) ;

上述代码的执行结果,pob1会接收到123456,而pob2收不到任何数据

replay 操作符


  1. replay()

replay操作符生成的ConnectableObservable,无论观察者什么时候订阅,都能收到Observable发送的所有数据

ConnectableObservable<String> connect = Observable.just("1","2","3","4","5","6").replay() ;//订阅代码省略。。。。connect.connect();   // 开始发送数据


  1. replay(int buffersize)

buffersize:ConnectableObservable缓存数据源的个数,凡是在connect()之后订阅的观察者,只能收到缓存的数据,connect()之前订阅的可以收到所有数据。说白了,replay()相当于缓存了所有数据源,而replay(int buffersize)缓存指定个数的数据源。
  • replay(long time, TimeUnit unit)
    time:ConnectableObservable换存数据源的时间,凡是在connect之后time时间内订阅的,可接收到所有数据,time时间之后订阅的,收不到任何数据。connect()之前订阅的,可收到所有数据。
  • replay(Scheduler scheduler)
    指定订阅和观察所在的工作线程。
  • replay(int buffersize, long time, TimenUnit unit)
    这个方法没什么可说的,结合2、3和容易理解。
  • replay(int buffersize, Scheduler scheduler)
    指定工作线程,并指定ConnectableObservable缓存数据源的个数。
  • replay(long time, Timeunit unit, Scheduler scheduler)
    指定工作线程,并指定数据源缓存时间。
  • replay(int buffersize, long time, TimeUnit unit, Scheduler scheduler)
    这个replay涵盖了以上所有的情况,我们在此用完整代码写一遍,并验证ConnectableObservable线程切换的问题。
  • /**     * ConnectableObservable用法和工作线程验证     * @throws InterruptedException     */    public void rxJavaReplayConnectObservable() throws InterruptedException {        List<String> datas = Arrays.asList("A","B","C","E","F","G") ;        // 1. 缓存3个数据,保留缓存2秒钟,不指定执行线程(默认在调用线程)        ConnectableObservable<String> connect = Observable.fromIterable(datas).replay(3, 2, TimeUnit.SECONDS) ;        // 2. 指定在新开线程执行,此时如果显示Toast,会报错:子线程不能更新UI        //ConnectableObservable<String> connect = Observable.fromIterable(datas).replay(3, 2, TimeUnit.SECONDS, Schedulers.newThread()) ;        // 3. 如果使用1(即:不指定工作线程),即使在此设置订阅线程和观察线程,也不起作用        // 验证了上文所说的,ConnectableObservable只支持replay操作符指定的工作线程,下面2代码不起作用        connect.subscribeOn(Schedulers.newThread()) ;        connect.subscribeOn(AndroidSchedulers.mainThread()) ;        // connect()之前订阅,将收到所有数据:A、B、C、D、E、F、G        connect.subscribe(getObserver("Observer-1", true)) ;        // 链接,Observable开始发送数据        connect.connect() ;        // 2. 如果打开休眠3秒的方法,Observer-2,因为超过了2秒的缓存,将收不到任何数据        // Thread.sleep(3000);        // connect()之后订阅,只能收到缓存的3个数据:E、F、G        connect.subscribe(getObserver("Observer-2", false)) ;    }    private Consumer<String> getObserver(final String tag, final boolean showToast){        return new Consumer<String>() {            boolean isFirst = true ;            @Override            public void accept(@NonNull String s) throws Exception {                Log.i(TAG, tag+":>>>>>>>>>"+s) ;                if(isFirst && showToast){                    Toast.makeText(mContext, tag+">>>>>>>显示成功", Toast.LENGTH_SHORT).show();                }            }        } ;    }

    PS:有兴趣的话,可以复制代码自己运行验证一下(我已经验证过了,不在贴运行结果了,注释很详细,而且通过修改部分参数会有很多种执行结果)。这个最复杂的replay函数会用了,其他几个简单的不在话下。

    总结

    因为我有Rxjava1.0的基础,所以我是通过github上的Rxjava2的例子去学习Rxjava2的,遇到不懂地方就去官方api中学习,csdn上做记录,可能有点杂乱无章,我会慢慢整理,争取慢慢进步。