FreshMVVM中从推送通知打开页面及后续导航异常问题
问题分析与解决方案
环境信息
- Xamarin.Forms 5.0.0.2401
- FreshMVVM 4.0.1
- 运行平台:Android、iOS
问题现象
尝试通过FreshMVVM打开页面时,若应用已运行则接入现有导航栈,页面能正常打开,但后续调用PushPageModel推送新页面时抛出异常:
FreshTinyIoC.TinyIoCResolutionException: 'Resolve failed: IFreshNavigationService'
异常调用栈
at FreshTinyIoC.FreshTinyIoCContainer.ResolveInternal (FreshTinyIoC.FreshTinyIoCContainer+TypeRegistration registration, FreshTinyIoC.NamedParameterOverloads parameters, FreshTinyIoC.ResolveOptions options) [0x00136] in <244cbb4b2b78473caee762c4138df3f3>:0 at FreshTinyIoC.FreshTinyIoCContainer.Resolve (System.Type resolveType, System.String name) [0x00013] in <244cbb4b2b78473caee762c4138df3f3>:0 at FreshTinyIoC.FreshTinyIoCContainer.Resolve[ResolveType] (System.String name) [0x00001] in <244cbb4b2b78473caee762c4138df3f3>:0 at FreshMvvm.FreshTinyIOCBuiltIn.Resolve[ResolveType] (System.String name) [0x00006] in <c1f1d60a460941bc82899cfb78f0c2ec>:0 at FreshMvvm.PageModelCoreMethods.PushPageModelWithPage (Xamarin.Forms.Page page, FreshMvvm.FreshBasePageModel pageModel, System.Object data, System.Boolean modal, System.Boolean animate) [0x001ca] in <c1f1d60a460941bc82899cfb78f0c2ec>:0
触发异常的代码
return new FreshAwaitCommand(async (entryType, tcs) => { await this.CoreMethods.PushPageModel(typeof(SignalHistoryViewModel), null, false, true); tcs.SetResult(true); });
通知点击处理代码(原实现)
Type viewModelType = Helpers.SignalStateToViewModelHelper.GetSignalDetailViewModelType((State)Enum.Parse(typeof(State), signalState)); var navigationStack = Application.Current.MainPage as NavigationPage; if (navigationStack != null) { // Navigate within the existing navigation stack var pageModel = FreshPageModelResolver.ResolvePageModel(viewModelType, true); Device.BeginInvokeOnMainThread(async () => { await navigationStack.PushAsync(FreshPageModelResolver.ResolvePageModel(viewModelType, null)); }); } else { // Create a new navigation stack var pageModel = FreshPageModelResolver.ResolvePageModel(viewModelType, true); var navigationContainer = new FreshNavigationContainer(pageModel); Device.BeginInvokeOnMainThread(() => { Application.Current.MainPage = navigationContainer; }); }
问题原因
直接使用原生NavigationPage.PushAsync推送FreshMVVM页面时,页面对应的ViewModel没有被正确注入IFreshNavigationService。FreshMVVM的CoreMethods.PushPageModel依赖该服务完成导航,因此后续调用时会因无法解析服务抛出异常。
解决方案
修改通知点击的处理逻辑,通过FreshMVVM自带的FreshNavigationService来完成页面推送,确保ViewModel与导航服务正确关联。
修改后的代码
Type viewModelType = Helpers.SignalStateToViewModelHelper.GetSignalDetailViewModelType((State)Enum.Parse(typeof(State), signalState)); // 直接获取FreshMVVM的导航容器 var freshNavContainer = Application.Current.MainPage as FreshNavigationContainer; if (freshNavContainer != null) { Device.BeginInvokeOnMainThread(async () => { // 使用FreshNavigationService推送页面 await freshNavContainer.NavigationService.PushPageModel(viewModelType, null, animate: true); }); } else { // 原有创建新导航容器的逻辑保持不变 var pageModel = FreshPageModelResolver.ResolvePageModel(viewModelType, true); var navigationContainer = new FreshNavigationContainer(pageModel); Device.BeginInvokeOnMainThread(() => { Application.Current.MainPage = navigationContainer; }); }
另一种实现方式(通过IoC解析导航服务)
如果确认IFreshNavigationService已被正确注册(创建FreshNavigationContainer时会自动完成注册),也可以直接从IoC容器解析服务:
Type viewModelType = Helpers.SignalStateToViewModelHelper.GetSignalDetailViewModelType((State)Enum.Parse(typeof(State), signalState)); Device.BeginInvokeOnMainThread(async () => { var navigationService = FreshTinyIoCContainer.Current.Resolve<IFreshNavigationService>(); await navigationService.PushPageModel(viewModelType, null, animate: true); });
内容的提问来源于stack exchange,提问作者Pat Long - Munkii Yebee
相关产品推荐
相关产品推荐

