UniRx_UniTask_学习记录_2.1_Observable 是什么

第二章 UniRx的动作原理

2.1 Observable 是什么

2.1.1 事件驱动程序

​ 当应用程序在执行中发生了事件,通过发送事件消息来通知。这个事件消息在别的地方被订阅,执行接收到消息后的处理。

2.1.2 Observer Pattern(观察者模式)

​ UniRx是在观察者模式到基础上制作的。

  • 观察者模式概要

    • Observer Object:事件消息观察者。事件消息的接收方。接收事件消息,并对其进行处理。
    • Subject Object:事件消息的发行方。可以登陆多个观察对象,当事件发行时通知所有观察者。
  • 观察者接口 interface IObserver

    using System;
    
    namespace System
    {
    		public interface IObserver<in T>
        {
          	// 事件发行,正常接收事件消息
          	void OnNext(T value);
          	// 发行中,异常发生时
          	void OnError(Exception error); 
          	// 事件消息发行完,正常结束后
          	void OnCompleted();
        }
    }
    
  • 接收观察对象的 interface IObservable

    IObservable 是接收 IObserver的接口

      namespace System
      {
        public interface IObservable<out T>
        {
          //IObserver<T> 作为参数 返回IDisposable借口
          IDisposable Subscribe(IObserver<T> observer);
        }
      }
    

    继承IObservable的对象,通过Subscribe(),对观察者进行登陆。

    并通过返回值的IDisposable的Dispose()方法对登陆的观察者进行解除。

    Subject继承IObservable的

  • Observer对象进行管理的【Subject】

    UniRx提供了Subject Class;

    • 用途

    • 特征

      继承了IObserver和IObservable

      可以同时对事件消息进行输入和输出

      可以登陆多个IObserver

      ISubject

      using System;
      namespace UniRx
      {
        public interface ISubject<TSource,TResult> : IObserver<TSource>,IObservable<TResult>
        {
          
        }
        
        public interface ISubject<T> : ISubject<T,T>,IObserver<T>,IObservable<T>
        {
          
        }
      }
      
  • Subject的利用例

    using System;
    
    namespace Sample.Section2.MyObservers
    {
        //继承IObserver<T> 用来打印消息的Observer
        public class PrintLogObserver<T> : IObserver<T>
        {
            public void OnCompleted()
            {
                UnityEngine.Debug.Log("OnCompleted");
            }
    
            public void OnError(Exception error)
            {
                UnityEngine.Debug.LogError(error);
            }
    
            public void OnNext(T value)
            {
                UnityEngine.Debug.Log(value);
            }
        }
    }
    
    using System;
    using System.Collections;
    using UniRx;
    using UnityEngine;
    
    namespace Sample.Section2.MyObservers
    {
        //指定倒计时 事件通知
        public class CountDownEventProvider : MonoBehaviour
        {
            [SerializeField] private int _countSeconds = 10;
    
            //Subject 
            private Subject<int> _subject;
            
            //只公开 Subject 的IObservable的接口
            public IObservable<int> CountDownObservable => _subject;
    
            private void Awake()
            {
                //Subject 生成
                _subject = new Subject<int>();
                
                //开启 倒计时协程
                StartCoroutine(CountCoroutine());
            }
    
            private IEnumerator CountCoroutine()
            {
                var current = _countSeconds;
    
                while (current > 0)
                {
                    //发行现在的值
                    _subject.OnNext(current);
                    current--;
                    yield return new WaitForSeconds(1f);
                }
                //最后发行 0 和 OnComplete
                _subject.OnNext(0);
                _subject.OnCompleted();
            }
    
            private void OnDestroy()
            {
                //当GameObject销毁是 释放Subject
                _subject.Dispose();
            }
        }
    }
    
    using System;
    using UnityEngine;
    
    namespace Sample.Section2.MyObservers
    {
        public class ObserveEventComponent : MonoBehaviour
        {
            [SerializeField] private CountDownEventProvider _countDownEventProvider;
            //Observer 
            private PrintLogObserver<int> _printLogObserver;
            private IDisposable _disposable;
    
            private void Start()
            {
                //PrintLogObserver 
                _printLogObserver = new PrintLogObserver<int>();
    
                //调用 Subject 的 Subscribe ,登陆 observer
                _disposable = _countDownEventProvider
                    .CountDownObservable
                    .Subscribe(_printLogObserver);
            }
    
            private void OnDestroy()
            {
                //GameObject 销毁时 注销事件
                _disposable?.Dispose();
            }
        }
    }
    
  • 实现下简单的Subject

    using System;
    using UniRx;
    using System.Collections.Generic;
    
    namespace Sample.Section2.MySubjects
    {
        //简单的MySubject
        public class MySubject<T> : ISubject<T>,IDisposable
        {
            public bool IsStopped { get; } = false;
            public bool IsDisposed { get; } = false;
    
            private readonly object _lockObject = new object();
            
            //途中发生的异常
            private Exception _error;
            
            //登陆的 Observer List
            private List<IObserver<T>> _observers;
    
            public MySubject()
            {
                _observers = new List<IObserver<T>>();
            }
            //实现 IObserver.OnNext
            public void OnNext(T value)
            {
                if (IsStopped) return;
                lock (_lockObject)
                {
                    ThrowIfDisposed();
                    //把消息传给所有的observer
                    foreach (var observer in _observers)
                    {
                        observer.OnNext(value);
                    }
                }
            }
            //实现Observer.OnError
            public void OnError(Exception error)
            {
                lock (_lockObject)
                {
                    ThrowIfDisposed();
                    if (IsStopped) return;
                    this._error = error;
    
                    try
                    {
                        foreach (var observer in _observers)
                        {
                            observer.OnError(_error);
                        }
                    }
                    finally
                    {
                        Dispose();
                    }
                }
            }
         
            //实现Observer.OnCompleted
            public void OnCompleted()
            {
                lock (_lockObject)
                {
                    ThrowIfDisposed();
                    if (IsStopped) return;
                    try
                    {
                        foreach (var observer in _observers)
                        {
                            observer.OnCompleted();
                        }
                    }
                    finally
                    {
                        Dispose();
                    }
                }
            }
            //实现IObservable.Subscribe 
            public IDisposable Subscribe(IObserver<T> observer)
            {
                lock (_lockObject)
                {
                    //如果已经结束 发行OnError 或者OnCompleted
                    if (IsStopped)
                    {
                        if (_error != null)
                        {
                            observer.OnError(_error);
                        }
                        else
                        {
                            observer.OnCompleted();
                        }
    
                        return Disposable.Empty;
                    }
                    _observers.Add(observer);//添加到List里
                    return new Subscription(this, observer);
                }
            }
            
            private void ThrowIfDisposed()
            {
                if (IsDisposed)
                    throw new ObjectDisposedException("MySubject");
            }
    
            public void Dispose()
            {
                lock (_lockObject)
                {
                    if (!IsDisposed)
                    {
                        _observers.Clear();
                        _observers = null;
                        _error = null;
                    }
                }
            }
            //
            private sealed class Subscription : IDisposable
            {
                private readonly IObserver<T> _observer; 
                private readonly MySubject<T> _parent;
                public Subscription(MySubject<T> parent, IObserver<T> observer)
                {
                    this._parent = parent;
                    this._observer = observer;
                }
                public void Dispose() {
                    // Dispose 的时候从 List里删除
                    _parent._observers.Remove(_observer);
                }
    
            }
        }
    }
    
  • 更简单的Subscribe()

    使用语法糖可以更简单优雅的处理事件消息

    using System;
    using UnityEngine;
    using UniRx;
    
    namespace Sample.Section2.MyObservers
    {
        public class ObserveEventComponent2 : MonoBehaviour
        {
            [SerializeField]
            private CountDownEventProvider _countDownEventProvider;
            private PrintLogObserver<int> _printLogObserver;
            private IDisposable _disposable;
    
            private void Start()
            {
                _disposable = _countDownEventProvider
                    .CountDownObservable
                    .Subscribe(
                        x => Debug.Log(x), // OnNext
                        ex => Debug.LogError(ex), // OnError
                        () => Debug.Log("OnCompleted!")); // OnCompleted
            }
            private void OnDestroy() 
            {
                _disposable?.Dispose();
            }
        }
    }
    

2.1.3 从观察者模式考虑Observable

  • Operator

    输出IObservable

    输入IObserver 对输入的消息进行加工

    使用咧

    using System;
    using UniRx;
    using UnityEngine;
    
    namespace Sample.Section2.Operators
    {
        //对消息进行过滤
        public class OperatorTest : MonoBehaviour
        {
            private void Start()
            {
                var subject = new Subject<int>();
    
                //直接订阅
                subject.Subscribe(x => Debug.Log("raw: " + x));
    
                //过滤 0以下的数
                subject
                    .Where(x => x > 0)
                    .Subscribe(x => Debug.Log("filter: " + x));
                
                // 发行消息
                subject.OnNext(1); 
                subject.OnNext(-1); 
                subject.OnNext(3); 
                subject.OnNext(0);
                // 结束
                subject.OnCompleted(); 
                subject.Dispose();
            }
        }
    }
    
  • Operator和Subject的不同

    • 两个都有IObserver和IObservable, 都可以对消息进行输入和输出
    • Subject 内部有一个List<IObserver> 可以储存多个IObserver
    • Operator没有,
  • Scheduler

    • 消息处理的时机和线程进行处理
      • Observable.Time / Observable.Interval
      • Delay / Timeout.

2.1.4 Observable

  • 简单来说 处理消息的流程 消息流 就称为Observable
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值