• Rxjava cold/hot Observable


    create

    Observable分为cold以及hot两种,cold主要是静态的,每次subscribe都是从头开始互不干扰,而hot的在同一时刻获得的值是一致的

    cold Observable

    使用create创建的Observable都是属于cold的Observable

    @Test
    public void coldObs() throws InterruptedException {
        Observable obs=Observable.create(sub->{
    		//在新线程上emit对象
            new Thread(()->{
            int i=0;
            while(i<5){
                sub.onNext(i++);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }}).start();
        });
        obs.subscribe(x->System.out.println("1st sub "+x));
        Thread.sleep(1000);
        obs.subscribe(x->System.out.println("2nd sub "+x));
        while(true){
            Thread.sleep(10000);
        }
    }
    -----输出-----
    1st sub 0
    1st sub 1
    2nd sub 0
    1st sub 2
    2nd sub 1
    1st sub 3
    2nd sub 2
    1st sub 4
    2nd sub 3
    2nd sub 4
    

    可以看到两个subscribe相隔1s订阅,两个值互不相关。

    hot Observable

    coldObs可以转换为hotObservable,hot主要是使用在比如鼠标操作等事件上的

    @Test
    public void hotObs() throws InterruptedException {
        ConnectableObservable obs=Observable.create(sub->{
    		//在新线程上emit对象
            new Thread(()->{
                int i=0;
                while(i<5){
                    sub.onNext(i++);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                    }
                }}).start();
        }).publish();
    	//开始emit对象
        obs.connect();
        obs.subscribe(x->System.out.println("1st sub "+x));
        Thread.sleep(1000);
        obs.subscribe(x->System.out.println("2nd sub "+x));
        while(true){
            Thread.sleep(10000);
        }
    }
    -----输出-----
    1st sub 1
    1st sub 2
    1st sub 3
    2nd sub 3
    1st sub 4
    2nd sub 4
    

    使用publish和connect之后就开始向subscriber发送对象,无论当前有几个subscriber,同一时刻subscriber得到的值也是一样的

    源码分析

    RxJava中有内置的钩子函数可以将函数注册在RxJavaHooks的各个方法上来改变各个环节的操作,包括Observable创建,运行时等
    Observable的create方法只是注册了对应emit的OnSubscribe对象

        public static <T> Observable<T> create(OnSubscribe<T> f) {
    		//调用protected构造方法,这里使用RxJavaHooks的onCreate方法
            return new Observable<T>(RxJavaHooks.onCreate(f));
        }
    	protected Observable(OnSubscribe<T> f) {
            this.onSubscribe = f;
        }
    

    正真运行Observable的是subscriber订阅时触发的

    public final Subscription subscribe(Subscriber<? super T> subscriber) {
        return Observable.subscribe(subscriber, this);
    }
    
    static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
        if (subscriber == null) {
            throw new IllegalArgumentException("subscriber can not be null");
        }
        if (observable.onSubscribe == null) {
            throw new IllegalStateException("onSubscribe function can not be null.");
        }
    
    	//调用subscriber的onStart方法
        subscriber.onStart();
    
        //使用SafeSubscriber包装原有的Subscriber,SafeSubscriber装饰原来的Subscriber保证当调用onComplete或onError后不会再调用任何方法。
        if (!(subscriber instanceof SafeSubscriber)) {
            subscriber = new SafeSubscriber<T>(subscriber);
        }
    
        try {
    		//使用JavaHooks的onObservableStart拦截的onSubscribe,并调用subscriber
            RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);
    		//当结束调用RxJavaHooks的onObservableReturn拦截方法
            return RxJavaHooks.onObservableReturn(subscriber);
        } catch (Throwable e) {
    		...
        }
    }
    

    这个是cold Observable的流程,下面看下Observable的publish和connect的逻辑

    //Observable.java
    //publish方法包装原来的Observable返回ConnectableObservable
    public final ConnectableObservable<T> publish() {
        return OperatorPublish.create(this);
    }
    
    //OperatorPublish.java
    public static <T> ConnectableObservable<T> create(Observable<? extends T> source) {
    	//订阅在原始Observable上的Subscriber
        final AtomicReference<PublishSubscriber<T>> curr = new AtomicReference<PublishSubscriber<T>>();
    	//ConnectableObservable的OnSubscribe,提供外界Subscriber订阅
        OnSubscribe<T> onSubscribe = new OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> child) {
                for (;;) {
                    PublishSubscriber<T> r = curr.get();
                    if (r == null || r.isUnsubscribed()) {
    					//这个Subscriber是用于订阅到原始Observable上的,这里只是初始化,并没有开始订阅
                        PublishSubscriber<T> u = new PublishSubscriber<T>(curr);
                        u.init();
                        if (!curr.compareAndSet(r, u)) {
                            continue;
                        }
                        r = u;
                    }
    
                    InnerProducer<T> inner = new InnerProducer<T>(r, child);
    				 //将订阅的子subscriber添加到PublishSubscriber上
                    if (r.add(inner)) {
                        child.add(inner);
                        child.setProducer(inner);
                        break; // NOPMD
                    }
                }
            }
        };
        return new OperatorPublish<T>(onSubscribe, source, curr);
    }
    
    //connect方法将PublishSubscriber订阅到原始的Observable,
    //ConnectableObservble.java
    public final Subscription connect() {
        final Subscription[] out = new Subscription[1];
    	//调用OperatorPublish的connect方法
        connect(new Action1<Subscription>() {
            @Override
            public void call(Subscription t1) {
                out[0] = t1;
            }
        });
        return out[0];
    }
    
    //OperatorPublish.java
    public void connect(Action1<? super Subscription> connection) {
        boolean doConnect;
        PublishSubscriber<T> ps;
    	//防止竞态条件使用CAS来初始化PublishSubscriber
        for (;;) {
            ps = current.get();
            if (ps == null || ps.isUnsubscribed()) {
                PublishSubscriber<T> u = new PublishSubscriber<T>(current);
                u.init();
                if (!current.compareAndSet(ps, u)) {
                    continue;
                }
                ps = u;
            }
            doConnect = !ps.shouldConnect.get() && ps.shouldConnect.compareAndSet(false, true);
            break; // NOPMD
        }
        connection.call(ps);
        if (doConnect) {
    		//如果之前没有订阅过,那么就订阅到原始的Observable上
            source.unsafeSubscribe(ps);
        }
    }
    
    //PublishSubscriber.java
    //这个是订阅到原始Observable上的Subscriber,当触发onNext时的逻辑
    public void onNext(T t) {
    	//将原始Observable发出的对象放入一个队列
        if (!queue.offer(NotificationLite.next(t))) {
            onError(new MissingBackpressureException());
        } else {
    		//调用dispatch方法可以将队列的内容发送个订阅的子Subscriber
            dispatch();
        }
    }
    
    //将值分发到各个子Subscriber上
    void dispatch() {
    	...
    	//从队列中取得值
        Object v = queue.poll();
    	...
    	//处理null
    	T value = NotificationLite.getValue(v);
    	...
    	//循环所有的InnerProducer(之前的在onSubscribe中add在Subsciber上的)
    	for (InnerProducer<T> ip : ps) {
    		if (ip.get() > 0L) {
    			try {
    				//把value传递给child的onNext
    				ip.child.onNext(value);
    			} catch (Throwable t) {
    				ip.unsubscribe();
    				Exceptions.throwOrReport(t, ip.child, value);
    				continue;
    			}
    			ip.produced(1);
    		}
    	}
    	...
    }
    

    hot的Observable就是自己监听原始的Observable然后广播给注册在上的子Subscriber,从而达到能够让所有子Subscriber取得一样的数据。

  • 相关阅读:
    Microsoft .NET 框架资源基础(摘自msdn)
    cache的应用
    cache应用(asp.net 2.0 + sqlserver2005 数据依赖缓存 )
    c#遍历查找指定文件
    各浏览器目前对CSS3、HTML5的支持
    一步步构建大型网站架构
    c#连接sqlserver数据库
    C#中如何判断一个字符是汉字
    c#执行DOC命令
    VS2010快捷键
  • 原文地址:https://www.cnblogs.com/resentment/p/5988247.html
Copyright © 2020-2023  润新知