UniRxのRepeat系のオペレータについてまとめました。
Repeat?
Repeatは、そのストリームがCompletedした際に、また新しく同じストリームを生成してSubscribe()します。
// 1秒おきにOn Next. と On Completed. が表示され続ける Observable.Timer(System.TimeSpan.FromSeconds(1)) .Do(_ => Debug.Log("On Next.")) .DoOnCompleted(() => Debug.Log("On Completed.")) .Repeat() .Subscribe() .AddTo(this);
無限ループの危険?
たとえば次のようなコードは無限ループになります。
Repeatを使うときには無限ループには気をつけないといけません。
// 無限ループ Observable.Range(0, 3) .Do(x => Debug.Log("On Next. " + x)) .DoOnCompleted(() => Debug.Log("On Completed.")) .Repeat() .Subscribe() .AddTo(this);
また、下記のようなケースも無限ループとなります。
これは、CompleteしているSubjectをRepeatによりひたすら購読し続けるためです。
// 無限ループ Subject<int> subject = new Subject<int>(); subject .Do(x => Debug.Log("On Next. " + x)) .DoOnCompleted(() => Debug.Log("On Completed.")) .Repeat() .Subscribe(); subject.OnCompleted();
RepeatSafe
RepeatSafeオペレータはOnCompletedが連続できたときにRepeatを止めます。
前節の二つの例のうちの後者は、これにより防げます。
// 無限ループしない Subject<int> subject = new Subject<int>(); subject .Do(x => Debug.Log("On Next. " + x)) .DoOnCompleted(() => Debug.Log("On Completed.")) .RepeatSafe() .Subscribe(); subject.OnCompleted();
ただ全ての無限ループが防げるわけではないので注意が必要です。
RepeatUntilDisable
RepeatUntilDisableはGameObjectが非アクティブになるまで繰り返します。
// GameObjectが非アクティブになるまで繰り返す Observable.Timer(System.TimeSpan.FromSeconds(1)) .Do(_ => Debug.Log("On Next.")) .DoOnCompleted(() => Debug.Log("On Completed.")) .RepeatUntilDisable(gameObject) .Subscribe() .AddTo(this);
RepeatUntilDestroy
RepeatUntilDisableはGameObjectが破棄されるまで繰り返します。
// GameObjectが破棄されるまで繰り返す Observable.Timer(System.TimeSpan.FromSeconds(1)) .Do(_ => Debug.Log("On Next.")) .DoOnCompleted(() => Debug.Log("On Completed.")) .RepeatUntilDestroy(gameObject) .Subscribe() .AddTo(this);