UniRX/Reactive 反应式编程 三元素

UniRX/Reactive 反应式编程 三元素

有关UniRX的基本概念不多说了,网上有很多反应式编程的介绍,主要元素如下:
在这里插入图片描述

这里主要结合源码,说明一下本人对各元素的理解

Observer

Observer 观察者,对应接口IObserver

public interface IObserver<in T>    
{         
 void OnCompleted();       
 void OnError(Exception error);  
 void OnNext(T value);    	   
}	

用于订阅(Subscribe)被观察者的消息或者事件。一般我们不会直接使用到它,大部分我们是使用匿名函数(lambda表达式),如下都是我们常用的方法:

 public static IDisposable Subscribe<T>(this IObservable<T> source)
 {
     return source.Subscribe(UniRx.InternalUtil.ThrowObserver<T>.Instance);
 }
 public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)
 {
     return source.Subscribe(Observer.CreateSubscribeObserver(onNext, Stubs.Throw, Stubs.Nop));
 }
 public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError)
 {
     return source.Subscribe(Observer.CreateSubscribeObserver(onNext, onError, Stubs.Nop));
 }
 public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted)
 {
     return source.Subscribe(Observer.CreateSubscribeObserver(onNext, Stubs.Throw, onCompleted));
 }
 public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted)
 {
     return source.Subscribe(Observer.CreateSubscribeObserver(onNext, onError, onCompleted));
 }

其本质是创建了Observer来接收事件的。

Observable

Observable 可观察的,对应接口IObservable,被观察者具有的特性。可以认为是被观察者的抽象定义。
在这里插入图片描述

上图可以看到其与Observer的关系

OperatorsOperators

操作符,其本质是提供了针对Observable一系列的操作,操作的返回还是一个Observable对象,以达到串联的效果,其是LING操作的一个超集,常用的操作比如,Where、Select等。其一般是通过Observable扩展的方式对外提供的。主要在代码在./Observable

public static IObservable<T> Where<T>(this IObservable<T> source, Func<T, int, bool> predicate)        
{            
	return new WhereObservable<T>(source, predicate);        
}

可以看到其返回的还是一个Observable对象,对应的WhereObservable定义在./Operators/Where.cs中,这个目录下还有很多的操作类定义

    internal class WhereObservable<T> : OperatorObservableBase<T>    
    {        
	readonly IObservable<T> source;        
	readonly Func<T, bool> predicate;        
	readonly Func<T, int, bool> predicateWithIndex;
	
	public WhereObservable(IObservable<T> source, Func<T, bool> predicate)            
        : base(source.IsRequiredSubscribeOnCurrentThread())        
        {            
	        this.source = source;            
	        this.predicate = predicate;        
        }

自定义Operators,也基于OperatorObservableBase进行扩展。其中的核心的代码:

protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)    
{        
	if (predicate != null)        
	{            
		return source.Subscribe(new Where(this, observer, cancel));        
	}        
	else        
	{            
		return source.Subscribe(new Where_(this, observer, cancel));        
	}    
}

其返回一个Where对象,可以看以下的代码

public abstract class OperatorObserverBase<TSource, TResult> : IDisposable, IObserver<TSource>    
{        
	protected internal volatile IObserver<TResult> observer;        
	IDisposable cancel;
        public OperatorObserverBase(IObserver<TResult> observer, IDisposable cancel)        	
        {            
	        this.observer = observer;            
	        this.cancel = cancel;        
        }
        public abstract void OnNext(TSource value);
        public abstract void OnError(Exception error);
        public abstract void OnCompleted();
   

其本身是一个Observer,它的OnNext方法只是调用构造时传入的Observer对象,事件触发时会先调用Where这个观察者,内部会判断是否满足Where的条件,如果满足调用传入的Observer的OnNext的方法。

总结一下,Operator 运算符 很确切的表达设计者的思想,如果从运算符的角度出发,具有传递性,它是一个桥梁,传递性体现在代码上有两个表示,

  • 一是调用的关系,比如:Observable.Start().Where().Select().Subscribe();
  • 一是内部Observer的传递,整个表达式,会构建一个Observer的列表,每一级会构建一个新的Obsever加入到列表中,队列的尾部为用户真正的处理代码,即调用Subscribe函数中的内容。

Subject

Subject 目标者,只是被观察者中的常用的实体类。UniRX最强大的地方就在于,可以把好多的对象,转化为可观察的,比如:Event、Task、Function等等。。。先看ISubject的定义如下:

public interface ISubject<T> : ISubject<T, T>, IObserver<T>, IObservable<T>    
{    
}

这里有点让人头大,Subject是被观察者,它为啥还要实现IObserver?这里可以理解Subject是目前UniRX中唯一可以主动触发的事件发起者,而这个触发者其实是调用者本身,所以它也是一个Observer。它可以一个发动机,通过一层层Observer的传递,最终调用用户Subscribe中的Lambda表达式。

Scheduler

IScheduler 与 TaskScheduler 的关系Scheduler即定义了事件触发时Observer运行的线程环境,分为

  1. NewThreadScheduler:即在新线程上执行
  2. ThreadPoolScheduler:即在线程池中执行
  3. TaskPoolScheduler:与ThreadPoolScheduler类似
  4. CurrentThreadScheduler:在当前线程执行
  5. ImmediateScheduler:在当前线程立即执行
  6. EventLoopScheduler:创建一个后台线程按序执行所有操作

注意: 这里当前线程说明一下,当前的含义是什么?是Subscribe调用者的当前线程,还是触发者的当前线程呢?通过简单的Debug,其是指触发者的当前线程,这里比较容易引起歧义。

DefaultScheduler

有以下几个值,用于不同的时机,或者是不同的Operator

   public static void SetDotNetCompatible()    
   {
           ConstantTimeOperations = Scheduler.Immediate;        
           TailRecursion = Scheduler.Immediate;        
           Iteration = Scheduler.CurrentThread;        
           TimeBasedOperations = Scheduler.ThreadPool;        
           AsyncConversions = Scheduler.ThreadPool;    
    }

后续

以上只是对UniRX的理解,各语言的Rx实现大致相同。开发者应用可以参考,用起来更加直观
https://www.cnblogs.com/Leo_wl/p/10400983.html
更加详细可以看看《Rx.NET In Action》这本书。

Githup

UniRX

发布了51 篇原创文章 · 获赞 10 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/FeiBin2013/article/details/102726465
今日推荐