我已經看過ReactiveUi從博客的例子,我想知道ReactiveUI是否有某種訂閱管理工具,或者是否忽視了它們可能會泄漏訂閱的例子?ReactiveUI是否泄漏訂閱?
任何時候我在ReactiveUi中調用一個導致IDisposable
的方法,是否需要保持該引用並自行跟蹤它?這也意味着我的ViewModel需要是一次性的,這似乎很難,因爲我們並不真正知道WPF中連接的「視圖」何時消失(即,如果我的ViewModel反映了數據網格中的項目),所以似乎沒有適當的放置處理。
我已經看過ReactiveUi從博客的例子,我想知道ReactiveUI是否有某種訂閱管理工具,或者是否忽視了它們可能會泄漏訂閱的例子?ReactiveUI是否泄漏訂閱?
任何時候我在ReactiveUi中調用一個導致IDisposable
的方法,是否需要保持該引用並自行跟蹤它?這也意味着我的ViewModel需要是一次性的,這似乎很難,因爲我們並不真正知道WPF中連接的「視圖」何時消失(即,如果我的ViewModel反映了數據網格中的項目),所以似乎沒有適當的放置處理。
如果您需要取消訂閱早期,您只需要保留對訂閱返回的IDisposable
的引用。當消息由OnCompleted
或OnError
消息終止時,自然會調用Dispose
。
但是,當您擁有無限可觀察訂閱(即FromEventPattern
)時,您需要保持引用,但這與在關閉表單/視圖之前需要刪除事件處理程序完全相同。
您還必須記住,Rx和ReactiveUI返回的IDisposables不與非託管內存相關聯 - 它們都只是簡單的.NET對象,仍由垃圾回收器重新指定。
您在ReactiveObjects的構造函數中製作的大部分訂閱將與主機對象的生命週期綁定 - 因此,當它超出範圍並受GC影響時,CLR將檢測到所有訂閱循環參考,只是核武的一切。
由於Enigmativity提到,最棘手的一點是,當您使用FromEventPattern將Subscription的生命週期(也許是ViewModel)與WPF對象的生命週期相關聯時。但是,我認爲如果您經常在ReactiveUI中使用FromEventPattern,那麼您肯定會做到錯誤™。
RxUI是所有的ViewModels和的ViewModels都是關於命令和性質(和接線,屬性是如何相互關聯的),所以你可以從它的視覺效果,分別測試的用戶體驗行爲 。
但是不是使用PropertyChanged和PropertyChanging事件中的EventPattern使用的ObservedChanged「events」嗎?而不是使用掛鉤到Executed事件的命令?我想這是令我擔心的。 – Damian 2012-01-26 13:37:01
不,內部ReactiveObject使用Subject,當您使用ObservableForProperty或WhenAny時,您沒有使用FromEventPattern – 2012-01-26 18:47:24
好吧。感謝您的澄清。我將Enigmativity的答案標記爲答案,因爲他是第一個答案,但您的澄清對我的轉換級別至關重要。 – Damian 2012-01-26 20:26:28
爲了安全起見,我將從現在開始使用這種模式。我可能會修改 通過擴展方法工作,但原則是健全的。爲了確保您 不漏要刪除他們
class Mesh2D{
public Mesh2D()
{
DisposeOnUnload(CreateBindings());
}
// Register all disposables for disposal on
// UIElement.Unload event. This should be
// moved to an extension method.
void DisposeOnUnload(IEnumerable<IDisposable> disposables)
{
var d = new CompositeDisposable(disposables);
var d2 = this.UnloadedObserver()
.Subscribe(e => d.Dispose());
var d3 = this.Dispatcher.ShutdownStartedObserver()
.Subscribe(e => d.Dispose());
d.Add(d2);
d.Add(d3);
}
// Where your bindings are simply yielded and
// they are removed on Unload magically
IEnumerable<IDisposable> CreateBindings()
{
// When the size changes we need to update all the transforms on
// the markers to reposition them.
yield return this.SizeChangedObserver()
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(eventArgs => this.ResetImageSource());
// If the points change or the viewport changes
yield return this.WhenAny(t => t.Mesh, t => t.Viewport, (x, t) => x.Value)
.Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler)
.Subscribe(t => this.UpdateMeshChanged());
}
}
注意我包裹RX FromEventPattern自動生成 擴展方法訂閱,所以我得到SizeChangedObserver()和UnloadedObserver() 免費,而不是難以記憶的FromEventPattern格式。
包裹代碼作爲這樣
public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){
return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h);
}
上述圖案生成很可能被用於解除綁定的IDisposable 視圖模型爲好。
通常情況下,如果發佈者的生命週期與用戶的生命週期相同或更短,您不必在表單關閉時刪除事件處理程序。例如,同樣的原則是否適用於ReactiveCommand? – KolA 2017-06-22 04:47:59
@KolA - 我建議你明確處理所有的Rx訂閱,如果你知道有些可能仍然運行只是爲了安全。很容易擁有一個表單級別的CompositeDisposable,可以跟蹤所有的訂閱。它意味着當你退出時只有一個'.Dispose()'。像常規活動一樣,您可能會在沒有這樣做的情況下離開,但情況並非總是如此。 – Enigmativity 2017-06-22 06:02:38