19 May 2017

核心思想

ReactiveX 的核心思想是将拉模型转化为推模型。以迭代器为例:

interface IEnumerable
{
    IEnumerator GetEnumerator();
}

interface IEnumerator: IDisposable
{
    bool MoveNext();
    object Current { get; }
}

上面是实现 C# 中迭代器的接口定义,我们需要不断的调用 MoveNext() 并根据其返回值决定是否调用 Current 属性。这是拉模型的实现方式,需要主动去请求并获取数据。

其对应的推模型接口定义如下:

interface IObservable
{
    IDisposable Subscribe(IObserver observer);
}

interface IObserver
{
    void OnNext(object value);
    void OnCompletion();
    void OnError(Exception ex);
}

推模型完全实现了拉模型的所有功能,只不过我们不再需要去主动请求并获取数据,而是订阅推送,当新消息出现时,会自动通知我们。这种模型极大地改善了诸如异步回调,并发,异常处理等编程方式,不再因为冗长的嵌套方式而导致回调地狱,也无需担心数据状态是否被并发所破坏,以及异常的流式处理。ReactiveX 的这种特性,也被简单地概括为异步的数据流

关键概念

学习 Rx,我们需要从 IObservableSubscribe 开始,即如何得到一个可观测对象和如何获取通知。

如何得到 IObservable

如何获取通知

ReactiveUI 应用场景演示

方便取消注册事件,解决内存泄露

如当我们需要在 Xamarin.iOS 中监测 UITextField 文本变化,通常我们可以注册 EditingChanged 事件获取通知,但在 Xamarin.iOS 中存在一个问题 Native 对象间的相互引用会导致内存泄露,这时,我们就不得不使用弱引用或在页面退出时手动取消注册事件等方式,书写起来会让代码显得很繁琐。ReactiveUI 为我们提供了注册以及取消注册的便捷方式:

this.WhenAnyValue(v => v.TextField.Text).Subscribe(x => { }).DisposeWith(bag);

bag 类型是 CompositeDisposable,通过将不同的订阅添加到 bag 中,可以很方便让我们对资源释放做统一处理。将观察操作放置到 ViewWillAppear 方法中,将释放操作 bag.Clear() 放置到 ViewWillDisappear 中,避免由于循环引用会导致 Dispose(bool) 方法不被调用。

通过 WhenAnyValue 检测 TextField 文本变化时需注意:手动通过代码改变文本不会触发该通知;可以使用 FromEventPattern 订阅 EditingChanged 事件 + TextField.SendActionForControlEvents(UIControlEvent.EditingChanged) 来实现最终效果。

.NET Reactive Framework / Getting Started with Rx / Subject/Observer is Dual to Iterator / Async JavaScript with Reactive Extensions