我应该如何从我的 ViewModel 上的 Rx 订阅执行 PushAsync 导航请求

How should I execute a PushAsync navigation request from an Rx subscription on my ViewModel

我在 Xamarin 表单中设置了一个 MVVM 样式的应用程序,我在其中通过 ViewModel 优先方法显示我的登录页面,该方法本身托管在 NavigationPage 中。

我注入了一个 INavigationService 实例,它建立了正确的导航 属性,如下所示:

var navigationController = Application.Current.MainPage as NavigationPage;

if (navigationController != null)
    return navigationController.Navigation;

什么时候可以像这样访问 PushAsync 方法:

public async Task PushAsync(INavigationPageModel page)
{
    var view = _viewFactory.CreatePage(page);
    await Navigation.PushAsync(view);
} 

现在,如果我在命令中使用此方法(例如),我发现我的视图已正确推送到导航堆栈上并且可以查看。但是,我正在使用 Rx 通过 BehaviourSubject 在我的应用程序上观察 'connected' 状态,这似乎给我带来了一些麻烦。

我没有收到任何错误,但我发现视图本身 似乎 被推入堆栈但对我不可见(我可以在调试器中的堆栈)。我只能假设这与 UI 线程有某种关系,但我不确定。

我的 RX 订阅已经经历了几次迭代,因为我似乎需要支持对异步方法的调用。目前看起来像这样:

_application.ConnectionManager.State
            .Where(s => s == ConnectionState.Connected)
            .SelectMany(l => Observable.FromAsync(ChangePageAsync))
            .SubscribeOn(Scheduler.UiScheduler)
            .Subscribe();

我的更改页面方法如下所示:

private Task ChangePageAsync()
{
    var viewModel = _viewModelFactory.CreateModel<DashboardPageViewModel>();
    return Navigation.PushAsync(viewModel);
}

为了完整起见,我在 AppDelegate 中为 iOS 应用程序捕获了 UI 调度程序,如下所示:

new SynchronizationContextScheduler(SynchronizationContext.Current);

正如我所说,我没有收到任何错误,但它只是没有通过 Rx 异步操作向我显示新页面。有任何想法吗?快把我逼疯了。

哦,抱歉,没有完全阅读代码。您需要使用 ObserveOn 而不是 SubscribeOn 并将其放在 SelectMany 之前。将其更改为:

_application.ConnectionManager.State
    .Where(s => s == ConnectionState.Connected)
    .ObserveOn(Scheduler.UiScheduler)
    .SelectMany(l => Observable.FromAsync(ChangePageAsync))
    .Subscribe();

这确保它在 UI 线程上 尝试更改页面之前。 SubscribeOn 用于确保订阅的脚手架在指定的调度程序上执行(通常在订阅阻塞时使用)。