zoukankan      html  css  js  c++  java
  • Handle navigation exceptions in Prism for Xamarin

    If you're using the NavigationService in Prism, for Xamarin.Forms or simply Xamarin, like this :

    navigationService.NavigateAsync(uri, parameters);
    
    1

    you might notice native crashes with no information or whatsoever.

    This happens when during the loading of the page and/or the navigation to it an exception is thrown. In that case you actually won't see any exception, the app will just crash and you will spend hours looking for an answer.

    The reason for that is that the NavigateAsync function is "awaitable" and returns a INavigationResult :

    namespace Prism.Navigation
    {
        public interface INavigationResult
        {
            bool Success { get; }
    
            Exception Exception { get; }
        }
    
        public class NavigationResult : INavigationResult
        {
            public bool Success { get; set; }
    
            public Exception Exception { get; set; }
        }
    }
    
    12345678910111213141516

    In order to handle this exception here is what I do :

    Method extensions

    I extend NavigateAsync functions with a TryNavigateAsync equivalent. The role of it is to handle the result of the navigation once it's done.

    public static async Task TryNavigateAsync(this INavigationService navigationService, Uri uri, INavigationParameters parameters = null)
    {
        var result = await navigationService.NavigateAsync(uri, parameters);
        HandleNavigationResult(result);
    }
    
    public static async Task TryNavigateModallyAsync(this INavigationService navigationService, Uri uri, INavigationParameters parameters = null)
    {
        var result = await navigationService.NavigateAsync(uri, parameters, true);
        HandleNavigationResult(result);
    }
    
    public static async Task TryNavigateAsync(this INavigationService navigationService, string path, INavigationParameters parameters = null)
    {
        var result = await navigationService.NavigateAsync(path, parameters);
        HandleNavigationResult(result);
    }
    
    public static async Task TryNavigateModallyAsync(this INavigationService navigationService, string path, INavigationParameters parameters = null)
    {
        var result = await navigationService.NavigateAsync(path, parameters, true);
        HandleNavigationResult(result);
    }
    
    public static async Task TryNavigateBackAsync(this INavigationService navigationService, INavigationParameters parameters = null)
    {
        var result = await navigationService.GoBackAsync(parameters);
        HandleNavigationResult(result);
    }
    
    1234567891011121314151617181920212223242526272829

    That enables you to use this line instead :

    // navigationService.NavigateAsync(uri, parameters);
    navigationService.TryNavigateAsync(uri, parameters);
    
    12

    Handle INavigationResult

    You want to test if your navigation was a success and, if not, do something with that exception :

    private static void HandleNavigationResult(INavigationResult navigationResult)
    {
        if (!navigationResult.Success)
        {
            Exception ex = new InvalidNavigationException();
            if (navigationResult.Exception != null)
                ex = navigationResult.Exception;
            SetMainPageFromException(ex);
        }
    }
    
    12345678910

    I created a new Exception for better logging purposes : InvalidNavigationException(), but if the inner navigation is given by Prism I will used the Prism one.

    Display the exception or throw it

    You can simply throw that exception if you want to. You might also just display it to yourself or in debug mode. Here is a little snippet to display that exception :

    private static void SetMainPageFromException(Exception ex)
    {
        var layout = new StackLayout
        {
            Padding = new Thickness(40)
        };
        layout.Children.Add(new Label
        {
            Text = ex?.GetType()?.Name ?? "Unknown Error encountered",
            FontAttributes = FontAttributes.Bold,
            HorizontalOptions = LayoutOptions.Center
        });
    
        layout.Children.Add(new ScrollView
        {
            Content = new Label
            {
                Text = $"{ex}",
                LineBreakMode = LineBreakMode.WordWrap
            }
        });
    
        PrismApplicationBase.Current.MainPage = new ContentPage
        {
            Content = layout
        };
    }
    
    123456789101112131415161718192021222324252627

    See the sample of all the code above being used in my Xamarin Developer Sample :

  • 相关阅读:
    2016年第9本:系统之美
    2016年第8本:不可思议的心理控制实验
    2016年第7本:非暴力沟通
    用SDWebImage渐变加载图片
    iOS相册、相机、通讯录权限获取
    屏蔽iOS10模拟器海量的垃圾debug信息
    Swift
    Swift
    PlaceholderImageView
    Swift
  • 原文地址:https://www.cnblogs.com/mschen/p/12181401.html
Copyright © 2011-2022 走看看