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

时间:2016-10-29 16:22:16

标签: c# mvvm xamarin.ios xamarin.forms system.reactive

我有一个以Xamarin形式设置的MVVM样式应用程序,我通过ViewModel第一种方法显示我的登录页面,该方法本身托管在NavigationPage中。

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

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

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

我没有收到任何错误,但我发现视图本身出现被推入堆栈但对我来说是不可见的(我可以在堆栈中看到它调试器)。我只能假设这与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);
}

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

new SynchronizationContextScheduler(SynchronizationContext.Current);

正如我所说,我没有错误,但它只是没有通过Rx异步动作向我显示新页面。有任何想法吗?它让我疯狂。

1 个答案:

答案 0 :(得分:1)

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

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

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