我应该如何从我的 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 用于确保订阅的脚手架在指定的调度程序上执行(通常在订阅阻塞时使用)。
我在 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 用于确保订阅的脚手架在指定的调度程序上执行(通常在订阅阻塞时使用)。