Is ReactiveUI Subscribing?

I looked at ReactiveUi examples from blogs, and I have to wonder if ReactiveUI has some kind of subscription management tool or examples that ignore the fact that they can flow under subscriptions?

Every time I call a method in ReactiveUi that leads to IDisposable , do I need to hold this link and track it myself? It also means that my ViewModels should be disposable, it seems difficult, since we really don’t know when the connected “Views” go away (i.e. if my ViewModel reflects the elements in the data grid) in WPF, so it seems not appropriate place to call.

+6
source share
3 answers

You only need to keep the links to the IDisposable returned by the subscriptions if you need to unsubscribe early on the observed one. Naturally, observables will call Dispose when they end with OnCompleted or OnError .

However, you need to keep the links when you have an endless observable subscription (i.e. FromEventPattern ), but this is exactly the same as removing event handlers before closing the form / view.

+10
source

You should also remember that the IDisposables returned by Rx and ReactiveUI are not unmanaged memory - these are just simple .NET objects still fixed by the garbage collector.

Most of the signatures created in the constructors of your ReactiveObjects will be tied to the lifetime of the host object, so when it goes beyond the scope and obeys the GC, like all subscriptions, the CLR detects a circular link and just bites everything.

As Enigmativity mentions, one tricky bit is when you use FromEventPattern to associate the lifetime of a subscription (and possibly ViewModel) with the lifetime of a WPF object. However, I would argue that you often use FromEventPattern in ReactiveUI, you definitely do Doing It Wrong ™.

RxUI is all about ViewModels, and ViewModels is all about commands and properties (and by linking properties related to each other), so you can test user experience behavior separately from your visual effects.

+13
source

To be safe, I will use this template from now on. I probably change the work using extension methods, but the principle sounds. To ensure you don’t miss the subscriptions you want to remove.

 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()); } } 

Note. I wrap the RX FromEventPattern with an automatically generated one so I get SizeChangedObserver () and UnloadedObserver () for free, and not the hard to remember FromEventPattern format.

The packaging code is created as such.

 public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){ return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h); } 

The above pattern can probably be used to unleash an IDisposable; also see the models.

+2
source

Source: https://habr.com/ru/post/906340/


All Articles