ReactiveUI WhenActivated 在 Android 上抛出 ObjectDisposedException
ReactiveUI WhenActivated throws ObjectDisposedException on Android
我们目前遇到 WhenActivated
版本 8 的问题。我们没有使用路由基础设施,而是使用内部 MVVM 框架。为了支持 ISupportActivation
我们在基页中监听 OnAppearing
和 OnDisapearing
事件并手动调用 Activate()
和 Deactivate()
.
以下内容曾经在版本 8 的 Alpha 版本中有效,但不再有效。 iOS.
中没有问题
下面的代码说明了这个问题,在 MainPage 上绑定了一个 ReactiveCommand,我们导航到 Target hello world 页面。可以找到一个回购 here
BaseContentPage
using System;
using ReactiveBug.ViewModels;
using ReactiveUI;
using ReactiveUI.XamForms;
using Xamarin.Forms;
namespace ReactiveBug.Pages
{
public class BaseContentPage<T> : ReactiveContentPage<T> where T : ReactiveBaseModel
{
public BaseContentPage()
{
this.Events().Appearing.Subscribe(args =>
{
if (ViewModel is ISupportsActivation activation)
{
Console.WriteLine($"Activating {GetType().Name}");
activation.Activator?.Activate();
}
});
this.Events().Disappearing.Subscribe(args =>
{
if (ViewModel is ISupportsActivation activation)
{
Console.WriteLine($"Deactivating {GetType().Name}");
activation.Activator.Deactivate();
}
});
}
}
}
MainPage VM(标签绑定到命令的空白页面)
using System;
using System.Reactive;
using System.Threading.Tasks;
using ReactiveBug.Pages;
using ReactiveUI;
using Xamarin.Forms;
namespace ReactiveBug.ViewModels
{
public class MainPageViewModel : ReactiveBaseModel
{
private ReactiveCommand<Unit, Unit> _labelClickCommand;
public MainPageViewModel(INavigation navigation) : base(navigation)
{
this.WhenActivated(d => { d(RxSetupLabelClickCommand()); });
}
public ReactiveCommand<Unit, Unit> LabelClickCommand
{
get => _labelClickCommand;
set => this.RaiseAndSetIfChanged(ref _labelClickCommand, value);
}
private async Task InternalLabelClickCommand()
{
Console.WriteLine($"{nameof(InternalLabelClickCommand)}");
var p = new TargetPage();
var vm = new TargetPageViewModel(p.Navigation);
p.ViewModel = vm;
await Navigation.PushAsync(p);
}
private IDisposable RxSetupLabelClickCommand()
{
Console.WriteLine($"{nameof(RxSetupLabelClickCommand)}");
LabelClickCommand = ReactiveCommand.CreateFromTask(InternalLabelClickCommand);
LabelClickCommand
.IsExecuting
.Subscribe(isExecuting => Console.Write($"{nameof(LabelClickCommand)}.IsExecuting: {isExecuting}"));
LabelClickCommand
.ThrownExceptions
.Subscribe(exception =>
Console.WriteLine($"Error executing {nameof(LabelClickCommand)}. Ex: {exception.ToString()}"));
return LabelClickCommand;
}
}
}
运行 这在 Android 上导致以下异常堆栈跟踪:
System.ObjectDisposedException: Cannot access a disposed object.
at System.Reactive.DisposedObserver`1[T].OnNext (T value) [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.Subject`1[T].OnNext (T value) [0x00000] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.SynchronizedObserver`1[T].OnNextCore (T value) [0x00011] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.ObserverBase`1[T].OnNext (T value) [0x0000d] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.Subject+AnonymousSubject`2[T,U].OnNext (T value) [0x00000] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at ReactiveUI.ReactiveCommand`2[TParam,TResult].<Execute>b__17_3 () [0x00000] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:860
at System.Reactive.Linq.ObservableImpl.Finally`1+_+<>c__DisplayClass2_0[TSource].<Run>b__0 () [0x0000d] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Disposables.AnonymousDisposable.Dispose () [0x00010] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Disposables.SingleAssignmentDisposable.set_Disposable (System.IDisposable value) [0x00028] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x0009a] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Linq.ObservableImpl.AsObservable`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x0000f] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.ConnectableObservable`2[TSource,TResult].Connect () [0x00019] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.RefCount`1+_[TSource].Run () [0x00053] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.RefCount`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x00010] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ObserveOn`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x00034] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].MoveNext () [0x00194] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Concurrency.AsyncLock.Wait (System.Action action) [0x000d0] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].<Run>b__7_0 (System.Action self) [0x00007] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Concurrency.Scheduler+<>c.<Schedule>b__47_0 (System.Action`1[T] _action, System.Action`1[T] self) [0x00014] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler+<>c__DisplayClass49_0`1[TState].<InvokeRec1>b__0 (TState state1) [0x0001e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState] (System.Reactive.Concurrency.IScheduler scheduler, System.Reactive.Concurrency.Scheduler+Pair`2[T1,T2] pair) [0x0004a] in <99f8205c51c44bb480747b577b8001ff>:0
at (wrapper delegate-invoke) System.Func`3[System.Reactive.Concurrency.IScheduler,System.Reactive.Concurrency.Scheduler+Pair`2[System.Action`1[System.Action],System.Action`2[System.Action`1[System.Action],System.Action`1[System.Action`1[System.Action]]]],System.IDisposable].invoke_TResult_T1_T2(System.Reactive.Concurrency.IScheduler,System.Reactive.Concurrency.Scheduler/Pair`2<System.Action`1<System.Action>, System.Action`2<System.Action`1<System.Action>, System.Action`1<System.Action`1<System.Action>>>>)
at System.Reactive.Concurrency.ImmediateScheduler.Schedule[TState] (TState state, System.Func`3[T1,T2,TResult] action) [0x00014] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.Schedule[TState] (System.Reactive.Concurrency.IScheduler scheduler, TState state, System.Action`2[T1,T2] action) [0x00042] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.Schedule (System.Reactive.Concurrency.IScheduler scheduler, System.Action`1[T] action) [0x0001c] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].Run (System.Collections.Generic.IEnumerable`1[T] sources) [0x00068] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.Catch`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x0000f] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].Run (System.Reactive.Concurrency.IScheduler _, System.Reactive.Producer`1+State[TSource] x) [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ScheduledItem`2[TAbsolute,TValue].InvokeCore () [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ScheduledItem`1[TAbsolute].Invoke () [0x0000d] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.CurrentThreadScheduler+Trampoline.Run (System.Reactive.Concurrency.SchedulerQueue`1[TAbsolute] queue) [0x00040] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState] (TState state, System.TimeSpan dueTime, System.Func`3[T1,T2,TResult] action) [0x00046] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.LocalScheduler.Schedule[TState] (TState state, System.Func`3[T1,T2,TResult] action) [0x0000e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x0005c] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].Subscribe (System.IObserver`1[T] observer) [0x0000e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.Subscribe[T] (System.IObservable`1[T] source) [0x00023] in <99f8205c51c44bb480747b577b8001ff>:0 Unhandled Exception:
System.ObjectDisposedException: Cannot access a disposed object.
at ReactiveUI.ReactiveCommandBase`2[TParam,TResult].ICommandExecute (System.Object parameter) [0x00048] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:721
at ReactiveUI.ReactiveCommand.System.Windows.Input.ICommand.Execute (System.Object parameter) [0x00000] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:622
at Xamarin.Forms.TapGestureRecognizer.SendTapped (Xamarin.Forms.View sender) [0x00018] in D:\a\s\Xamarin.Forms.Core\TapGestureRecognizer.cs:44
at Xamarin.Forms.Platform.Android.TapGestureHandler.OnTap (System.Int32 count) [0x00028] in D:\a\s\Xamarin.Forms.Platform.Android\TapGestureHandler.cs:37
at Xamarin.Forms.Platform.Android.InnerGestureListener.Android.Views.GestureDetector.IOnGestureListener.OnSingleTapUp (Android.Views.MotionEvent e) [0x00014] in D:\a\s\Xamarin.Forms.Platform.Android\InnerGestureListener.cs:140
at Android.Views.GestureDetector+IOnGestureListenerInvoker.n_OnSingleTapUp_Landroid_view_MotionEvent_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_e) [0x0000f] in <263adecfa58f4c449f1ff56156d886fd>:0
at (wrapper dynamic-method) System.Object.81a6100d-59c5-43e9-a3f0-6c38c921f2aa(intptr,intptr,intptr)
UNHANDLED EXCEPTION:
System.ObjectDisposedException: Cannot access a disposed object.
at (wrapper dynamic-method) System.Object.81a6100d-59c5-43e9-a3f0-6c38c921f2aa(intptr,intptr,intptr)
at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_call_nonvirtual_boolean_method_a(intptr,intptr&,intptr,intptr,intptr,Java.Interop.JniArgumentValue*)
at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualBooleanMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00073] in <7802aa64ad574c33adca332a3fa9706a>:0
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualBooleanMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0005d] in <7802aa64ad574c33adca332a3fa9706a>:0
at Android.Views.GestureDetector.OnTouchEvent (Android.Views.MotionEvent ev) [0x00031] in <263adecfa58f4c449f1ff56156d886fd>:0
at Xamarin.Forms.Platform.Android.GestureManager+TapAndPanGestureDetector.OnTouchEvent (Android.Views.MotionEvent ev) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\GestureManager.cs:87
at Xamarin.Forms.Platform.Android.GestureManager.OnTouchEvent (Android.Views.MotionEvent e) [0x0005c] in D:\a\s\Xamarin.Forms.Platform.Android\GestureManager.cs:59
at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].OnTouchEvent (Android.Views.MotionEvent e) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:38
有人知道发生了什么以及如何解决这个问题吗?
我可以回答两个问题之一。
how to fix this?
我见过很多 ReactiveUI 项目,但从未见过有人处理 ReactiveCommands。要记住的重要一点是处理 ReactiveCommand 订阅和绑定。
因此,如果您选择绑定 ReactiveUI 方式,而不是通过 xaml,您可以在 xaml 中执行以下操作:
<TapGestureRecognizer x:Name="TapGesture" />
并在 MainPage 构造函数中:
this.WhenActivated(
disposables =>
{
this.OneWayBind(ViewModel, vm => vm.LabelClickCommand, v => v.TapGesture.Command)
.DisposeWith(disposables);
});
并且在 ViewModel 中处理任何额外的订阅:
public MainPageViewModel(INavigation navigation) : base(navigation)
{
LabelClickCommand = ReactiveCommand
.CreateFromTask(InternalLabelClickCommand);
this.WhenActivated(
disposables =>
{
LabelClickCommand
.IsExecuting
.Subscribe(isExecuting => Console.Write($"{nameof(LabelClickCommand)}.IsExecuting: {isExecuting}"))
.DisposeWith(disposables);
LabelClickCommand
.ThrownExceptions
.Subscribe(exception =>
Console.WriteLine($"Error executing {nameof(LabelClickCommand)}. Ex: {exception.ToString()}"))
.DisposeWith(disposables);
});
}
我测试了这段代码,所以它按预期工作。
在您的解决方案中,我怀疑 LabelClickCommand 在它完成执行之前被处理掉了;因为我在 await 语句之后的右大括号处放置了一个断点,但它从未被击中。
不过话又说回来,你说它在 iOS 和 ReactiveUI 8 的 Alpha 版本中工作正常,所以我不确定。
很抱歉在这方面没有解释。希望其他人可以插话。在此之前,我希望这种替代方法能满足您的需求。
更新
正如格伦在评论中提到的,
Rx in general you don't want to necessarily dispose of everything (more vital on Mobile Apps for sure) due to performance issues.
Scope 确定您是否需要费心处理订阅。这是另一个 .
例如,您肯定想要处理以下订阅,特别是如果该服务具有完整的应用程序生命周期。否则,该服务将在视图模型被销毁后继续保留该订阅。
_someSubscription = someService
.SomePipeline
.Subscribe(x => ...);
相比之下,对 LabelClickCommand 的 ThrownExceptions 和 IsExecuting 的订阅具有本地作用域,因此您甚至不需要真正处理它们,就像我在上面所做的那样。
我们目前遇到 WhenActivated
版本 8 的问题。我们没有使用路由基础设施,而是使用内部 MVVM 框架。为了支持 ISupportActivation
我们在基页中监听 OnAppearing
和 OnDisapearing
事件并手动调用 Activate()
和 Deactivate()
.
以下内容曾经在版本 8 的 Alpha 版本中有效,但不再有效。 iOS.
中没有问题下面的代码说明了这个问题,在 MainPage 上绑定了一个 ReactiveCommand,我们导航到 Target hello world 页面。可以找到一个回购 here
BaseContentPage
using System;
using ReactiveBug.ViewModels;
using ReactiveUI;
using ReactiveUI.XamForms;
using Xamarin.Forms;
namespace ReactiveBug.Pages
{
public class BaseContentPage<T> : ReactiveContentPage<T> where T : ReactiveBaseModel
{
public BaseContentPage()
{
this.Events().Appearing.Subscribe(args =>
{
if (ViewModel is ISupportsActivation activation)
{
Console.WriteLine($"Activating {GetType().Name}");
activation.Activator?.Activate();
}
});
this.Events().Disappearing.Subscribe(args =>
{
if (ViewModel is ISupportsActivation activation)
{
Console.WriteLine($"Deactivating {GetType().Name}");
activation.Activator.Deactivate();
}
});
}
}
}
MainPage VM(标签绑定到命令的空白页面)
using System;
using System.Reactive;
using System.Threading.Tasks;
using ReactiveBug.Pages;
using ReactiveUI;
using Xamarin.Forms;
namespace ReactiveBug.ViewModels
{
public class MainPageViewModel : ReactiveBaseModel
{
private ReactiveCommand<Unit, Unit> _labelClickCommand;
public MainPageViewModel(INavigation navigation) : base(navigation)
{
this.WhenActivated(d => { d(RxSetupLabelClickCommand()); });
}
public ReactiveCommand<Unit, Unit> LabelClickCommand
{
get => _labelClickCommand;
set => this.RaiseAndSetIfChanged(ref _labelClickCommand, value);
}
private async Task InternalLabelClickCommand()
{
Console.WriteLine($"{nameof(InternalLabelClickCommand)}");
var p = new TargetPage();
var vm = new TargetPageViewModel(p.Navigation);
p.ViewModel = vm;
await Navigation.PushAsync(p);
}
private IDisposable RxSetupLabelClickCommand()
{
Console.WriteLine($"{nameof(RxSetupLabelClickCommand)}");
LabelClickCommand = ReactiveCommand.CreateFromTask(InternalLabelClickCommand);
LabelClickCommand
.IsExecuting
.Subscribe(isExecuting => Console.Write($"{nameof(LabelClickCommand)}.IsExecuting: {isExecuting}"));
LabelClickCommand
.ThrownExceptions
.Subscribe(exception =>
Console.WriteLine($"Error executing {nameof(LabelClickCommand)}. Ex: {exception.ToString()}"));
return LabelClickCommand;
}
}
}
运行 这在 Android 上导致以下异常堆栈跟踪:
System.ObjectDisposedException: Cannot access a disposed object.
at System.Reactive.DisposedObserver`1[T].OnNext (T value) [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.Subject`1[T].OnNext (T value) [0x00000] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.SynchronizedObserver`1[T].OnNextCore (T value) [0x00011] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.ObserverBase`1[T].OnNext (T value) [0x0000d] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.Subject+AnonymousSubject`2[T,U].OnNext (T value) [0x00000] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at ReactiveUI.ReactiveCommand`2[TParam,TResult].<Execute>b__17_3 () [0x00000] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:860
at System.Reactive.Linq.ObservableImpl.Finally`1+_+<>c__DisplayClass2_0[TSource].<Run>b__0 () [0x0000d] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Disposables.AnonymousDisposable.Dispose () [0x00010] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Disposables.SingleAssignmentDisposable.set_Disposable (System.IDisposable value) [0x00028] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x0009a] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Linq.ObservableImpl.AsObservable`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x0000f] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Subjects.ConnectableObservable`2[TSource,TResult].Connect () [0x00019] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.RefCount`1+_[TSource].Run () [0x00053] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.RefCount`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x00010] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ObserveOn`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x00034] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x00071] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.SubscribeSafe[T] (System.IObservable`1[T] source, System.IObserver`1[T] observer) [0x00036] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].MoveNext () [0x00194] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Concurrency.AsyncLock.Wait (System.Action action) [0x000d0] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].<Run>b__7_0 (System.Action self) [0x00007] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Concurrency.Scheduler+<>c.<Schedule>b__47_0 (System.Action`1[T] _action, System.Action`1[T] self) [0x00014] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler+<>c__DisplayClass49_0`1[TState].<InvokeRec1>b__0 (TState state1) [0x0001e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.InvokeRec1[TState] (System.Reactive.Concurrency.IScheduler scheduler, System.Reactive.Concurrency.Scheduler+Pair`2[T1,T2] pair) [0x0004a] in <99f8205c51c44bb480747b577b8001ff>:0
at (wrapper delegate-invoke) System.Func`3[System.Reactive.Concurrency.IScheduler,System.Reactive.Concurrency.Scheduler+Pair`2[System.Action`1[System.Action],System.Action`2[System.Action`1[System.Action],System.Action`1[System.Action`1[System.Action]]]],System.IDisposable].invoke_TResult_T1_T2(System.Reactive.Concurrency.IScheduler,System.Reactive.Concurrency.Scheduler/Pair`2<System.Action`1<System.Action>, System.Action`2<System.Action`1<System.Action>, System.Action`1<System.Action`1<System.Action>>>>)
at System.Reactive.Concurrency.ImmediateScheduler.Schedule[TState] (TState state, System.Func`3[T1,T2,TResult] action) [0x00014] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.Schedule[TState] (System.Reactive.Concurrency.IScheduler scheduler, TState state, System.Action`2[T1,T2] action) [0x00042] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.Scheduler.Schedule (System.Reactive.Concurrency.IScheduler scheduler, System.Action`1[T] action) [0x0001c] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.TailRecursiveSink`1[TSource].Run (System.Collections.Generic.IEnumerable`1[T] sources) [0x00068] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Linq.ObservableImpl.Catch`1[TSource].Run (System.IObserver`1[T] observer, System.IDisposable cancel, System.Action`1[T] setSink) [0x0000f] in <e9c1ccec51844dbd92b833a0b4bc960e>:0
at System.Reactive.Producer`1[TSource].Run (System.Reactive.Concurrency.IScheduler _, System.Reactive.Producer`1+State[TSource] x) [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ScheduledItem`2[TAbsolute,TValue].InvokeCore () [0x00000] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.ScheduledItem`1[TAbsolute].Invoke () [0x0000d] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.CurrentThreadScheduler+Trampoline.Run (System.Reactive.Concurrency.SchedulerQueue`1[TAbsolute] queue) [0x00040] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState] (TState state, System.TimeSpan dueTime, System.Func`3[T1,T2,TResult] action) [0x00046] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Concurrency.LocalScheduler.Schedule[TState] (TState state, System.Func`3[T1,T2,TResult] action) [0x0000e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].SubscribeRaw (System.IObserver`1[T] observer, System.Boolean enableSafeguard) [0x0005c] in <99f8205c51c44bb480747b577b8001ff>:0
at System.Reactive.Producer`1[TSource].Subscribe (System.IObserver`1[T] observer) [0x0000e] in <99f8205c51c44bb480747b577b8001ff>:0
at System.ObservableExtensions.Subscribe[T] (System.IObservable`1[T] source) [0x00023] in <99f8205c51c44bb480747b577b8001ff>:0 Unhandled Exception:
System.ObjectDisposedException: Cannot access a disposed object.
at ReactiveUI.ReactiveCommandBase`2[TParam,TResult].ICommandExecute (System.Object parameter) [0x00048] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:721
at ReactiveUI.ReactiveCommand.System.Windows.Input.ICommand.Execute (System.Object parameter) [0x00000] in D:\a\s\src\ReactiveUI\ReactiveCommand.cs:622
at Xamarin.Forms.TapGestureRecognizer.SendTapped (Xamarin.Forms.View sender) [0x00018] in D:\a\s\Xamarin.Forms.Core\TapGestureRecognizer.cs:44
at Xamarin.Forms.Platform.Android.TapGestureHandler.OnTap (System.Int32 count) [0x00028] in D:\a\s\Xamarin.Forms.Platform.Android\TapGestureHandler.cs:37
at Xamarin.Forms.Platform.Android.InnerGestureListener.Android.Views.GestureDetector.IOnGestureListener.OnSingleTapUp (Android.Views.MotionEvent e) [0x00014] in D:\a\s\Xamarin.Forms.Platform.Android\InnerGestureListener.cs:140
at Android.Views.GestureDetector+IOnGestureListenerInvoker.n_OnSingleTapUp_Landroid_view_MotionEvent_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_e) [0x0000f] in <263adecfa58f4c449f1ff56156d886fd>:0
at (wrapper dynamic-method) System.Object.81a6100d-59c5-43e9-a3f0-6c38c921f2aa(intptr,intptr,intptr)
UNHANDLED EXCEPTION:
System.ObjectDisposedException: Cannot access a disposed object.
at (wrapper dynamic-method) System.Object.81a6100d-59c5-43e9-a3f0-6c38c921f2aa(intptr,intptr,intptr)
at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_call_nonvirtual_boolean_method_a(intptr,intptr&,intptr,intptr,intptr,Java.Interop.JniArgumentValue*)
at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualBooleanMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00073] in <7802aa64ad574c33adca332a3fa9706a>:0
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualBooleanMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0005d] in <7802aa64ad574c33adca332a3fa9706a>:0
at Android.Views.GestureDetector.OnTouchEvent (Android.Views.MotionEvent ev) [0x00031] in <263adecfa58f4c449f1ff56156d886fd>:0
at Xamarin.Forms.Platform.Android.GestureManager+TapAndPanGestureDetector.OnTouchEvent (Android.Views.MotionEvent ev) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\GestureManager.cs:87
at Xamarin.Forms.Platform.Android.GestureManager.OnTouchEvent (Android.Views.MotionEvent e) [0x0005c] in D:\a\s\Xamarin.Forms.Platform.Android\GestureManager.cs:59
at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].OnTouchEvent (Android.Views.MotionEvent e) [0x00000] in D:\a\s\Xamarin.Forms.Platform.Android\VisualElementRenderer.cs:38
有人知道发生了什么以及如何解决这个问题吗?
我可以回答两个问题之一。
how to fix this?
我见过很多 ReactiveUI 项目,但从未见过有人处理 ReactiveCommands。要记住的重要一点是处理 ReactiveCommand 订阅和绑定。
因此,如果您选择绑定 ReactiveUI 方式,而不是通过 xaml,您可以在 xaml 中执行以下操作:
<TapGestureRecognizer x:Name="TapGesture" />
并在 MainPage 构造函数中:
this.WhenActivated(
disposables =>
{
this.OneWayBind(ViewModel, vm => vm.LabelClickCommand, v => v.TapGesture.Command)
.DisposeWith(disposables);
});
并且在 ViewModel 中处理任何额外的订阅:
public MainPageViewModel(INavigation navigation) : base(navigation)
{
LabelClickCommand = ReactiveCommand
.CreateFromTask(InternalLabelClickCommand);
this.WhenActivated(
disposables =>
{
LabelClickCommand
.IsExecuting
.Subscribe(isExecuting => Console.Write($"{nameof(LabelClickCommand)}.IsExecuting: {isExecuting}"))
.DisposeWith(disposables);
LabelClickCommand
.ThrownExceptions
.Subscribe(exception =>
Console.WriteLine($"Error executing {nameof(LabelClickCommand)}. Ex: {exception.ToString()}"))
.DisposeWith(disposables);
});
}
我测试了这段代码,所以它按预期工作。
在您的解决方案中,我怀疑 LabelClickCommand 在它完成执行之前被处理掉了;因为我在 await 语句之后的右大括号处放置了一个断点,但它从未被击中。
不过话又说回来,你说它在 iOS 和 ReactiveUI 8 的 Alpha 版本中工作正常,所以我不确定。
很抱歉在这方面没有解释。希望其他人可以插话。在此之前,我希望这种替代方法能满足您的需求。
更新
正如格伦在评论中提到的,
Rx in general you don't want to necessarily dispose of everything (more vital on Mobile Apps for sure) due to performance issues.
Scope 确定您是否需要费心处理订阅。这是另一个
例如,您肯定想要处理以下订阅,特别是如果该服务具有完整的应用程序生命周期。否则,该服务将在视图模型被销毁后继续保留该订阅。
_someSubscription = someService
.SomePipeline
.Subscribe(x => ...);
相比之下,对 LabelClickCommand 的 ThrownExceptions 和 IsExecuting 的订阅具有本地作用域,因此您甚至不需要真正处理它们,就像我在上面所做的那样。