17.UniRx序列(Sample、Scan、Switch、ToAwaitable/Wait、WithLastestFrom、De/Materialize、Multicast)

Sample()
Scan()
Switch()
ToAwaitableEnumerator()
Wait()
WithLatestFrom()
Materialize()
Dematerialize()
Multicast()


Sample/SampleFrame

對一個基礎流進行採樣,採樣的數據以基礎流最近輸出的一個數據爲準,圖解
在這裏插入圖片描述
第一條線是基礎流在輸出數據
第二條線是一個Sample的流在進行採樣
A採樣輸出1,他最近可取的數據爲1;B同理,C採樣不到數據,因爲C最近的數據已經被Sample了;
爲什麼C採樣不到3,因爲3沒有被輸出,C不知道有3的存在
結束採樣輸出了5,因爲採樣結束,基礎流在輸出,所以輸出了5

執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var sample = Observable.EveryUpdate().Sample(TimeSpan.FromMilliseconds(200));
        sample.Subscribe(Next, Error, Complete);
    }

    void Next(long frame)
    {
        Debug.LogFormat("Sample的幀:{0}", frame);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex);
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析


Scan

對流發出的數據進行掃描,將處理的結果返回到輸出,操作和內聚差不多,圖解
在這裏插入圖片描述
執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var scan = Observable.Range(1, 3).Scan(ScanMethod);
        scan.Subscribe(Next, Error, Complete);
    }

    // origin 1 2 3
    // result 1 3 6
    private int ScanMethod(int pre, int next)
    {
        return pre + next;
    }

    void Next(int result)
    {
        Debug.LogFormat("Scan之後的結果:{0}", result);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex);
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析
Range輸出的值是123,經過Scan之後是136,第一個Scan的pre值爲0


Switch

將多個獨立輸出流的輸出數據彙總到一個流裏面,圖解
在這裏插入圖片描述
第一條橫線是一個匯聚多個流的基礎流,在輸出數據,它由兩個流組成,輸出的數據分佈是圓形和三角形;
基礎流通過Switch之後,把所有的分支流全部彙總到一個流上輸出
結束以最後一個流的結束標誌位基準

執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var subject = new Subject<IObservable<int>>();

        var sources = subject.AsObservable();
        var @switch = Observable.Switch(sources);

        subject.Subscribe(Next);
        @switch.Subscribe(NextSwitch, ErrorSwitch, CompleteSwitch);

        subject.OnNext(Observable.Return(10));
        subject.OnNext(Observable.Return(30));
        subject.OnCompleted();
    }

    void Next(IObservable<int> observable)
    {
        observable.Subscribe(
             v => Debug.LogFormat("Next Sources:{0}", v),
         ()=> Debug.LogFormat("Next Complete"));
    }

    void NextSwitch(int value)
    {
        Debug.LogFormat("NextSwitch Sources:{0}", value);
    }

    void ErrorSwitch(Exception ex)
    {
        Debug.LogException(ex);
    }

    void CompleteSwitch()
    {
        Debug.LogFormat("NextSwitch Complete");
    }
}

代碼解析

自定義了一個主題,主題的包裝類型是一個流;AsObservable把主題當成一個流來處理,理論上來說主題每次Next一個流,讓流獨自去運作;每個流都會執行完整的,使用Switch之後,把主題包裝的集合流全部映射到一個流上,只有一個Complete執行,是我們手動調用的Complete方法。


ToAwaitableEnumerator

UniRx特有,將一個流轉換成一個可等待的協同,等待流的執行結果,有結果或錯誤信息

執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var subject = new Subject<int>();

        var enumerator = subject.ToAwaitableEnumerator(Result, Error);
        StartCoroutine(enumerator);
        var disposable = subject.Subscribe(Next, Error, Complete);

        subject.OnNext(10);
        subject.OnNext(30);
        subject.OnCompleted();
        disposable.AddTo(gameObject);
    }

    void Result(int value)
    {
        Debug.LogFormat("ToAwaitableEnumerator:{0}", value);
    }

    void Next(int next)
    {
        Debug.LogFormat("Subject Next:{0}", next);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex);
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析


Wait

UniRx特有,封裝線程之間通訊的操作,具體用法未知

執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var subject = new Subject<int>();
        subject.Subscribe(Next, Error, Complete);

        subject.OnNext(10);

        var wait = subject.Wait(TimeSpan.FromMilliseconds(1000));
        
        Debug.LogFormat("Wait:{0}", wait); 

        subject.OnNext(30);
        subject.OnCompleted();

    }

    void Next(int next)
    {
        Debug.LogFormat("Subject Next:{0}", next);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex); 
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析


WithLastestFrom

UniRx特有,操作兩個流,left和right,取右邊流最終的執行結果給left操作返回

執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var subject0 = new Subject<int>();
        var subject1 = new Subject<int>();

        var latest = subject0.WithLatestFrom(subject1, Selector);
        latest.Subscribe(Next, Error, Complete);

        subject0.OnNext(11);
        subject1.OnNext(22);
        subject1.OnNext(33);
        subject0.OnNext(44);
        subject0.OnNext(55);
    }

    private int Selector(int left, int right)
    {
        return left + right;
    }

    void Next(int next)
    {
        Debug.LogFormat("WithLatestFrom Next:{0}", next);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex); 
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析

通過WithLatestFrom,以右邊的流Subject1爲準,取Subject1流最後輸出的數據,當以後有數據執行的時候(Left)執行
Selector操作,取一個流最後的值,附加到另外一個操作流上返回執行結果。


Materialize

使得完整的流通過Materialize之後變成了單步執行,擁有全部的執行過程,圖解
在這裏插入圖片描述
執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var materialize = Observable.Range(1, 3).Materialize();
        materialize.Subscribe(Next, Error, Complete);
    }

    void Next(Notification<int> notification)
    {
        Debug.LogFormat("Materialize Next:{0}", notification);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex); 
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析


Dematerialize

和Materialize是功能相反的一對,將Materialize的單步劃分合併成一個完整的流,圖解
在這裏插入圖片描述
執行結果

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var materialize = Observable.Range(1, 3).Materialize().Dematerialize();
        materialize.Subscribe(Next, Error, Complete);
    }

    void Next(int value)
    {
        Debug.LogFormat("Dematerialize Next:{0}", value);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex); 
    }

    void Complete()
    {
        Debug.LogFormat("Complete");
    }
}

代碼解析


Multicast

功能和Pulish差不多,將流變成Connectable的流,再處理流的數據,可以指定一個Subject來同步輸出,圖解
在這裏插入圖片描述
執行結果
在這裏插入圖片描述
代碼示例

public class No17_Mixed7 : MonoBehaviour
{
    void Start()
    {
        var subject = new Subject<int>();
        subject.Subscribe(
            value => Debug.LogFormat("Subject Next:{0}", value),
            () => Debug.LogFormat("Subject Complete"));

        var multicast = Observable.Range(1, 3).Multicast(subject).RefCount();
        multicast.Subscribe(Next, Error, Complete);

    }

    void Next(int value)
    {
        Debug.LogFormat("Multicast Next:{0}", value);
    }

    void Error(Exception ex)
    {
        Debug.LogException(ex); 
    }

    void Complete()
    {
        Debug.LogFormat("Multicast Complete");
    }
}

代碼解析


總結

UniRx全部字段文檔已完結,之後補充UniRx專題相關的知識;UniRx必定是以後流行必備的一門編程語言技術,高度的靈活性,對功能的便捷和自由拓展能力,好比《我的世界》遊戲一般;使用了C#優美的異步,能夠讓使用者無論從畫質還是邏輯都能上升一個臺階。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章