如何在MauiApp创建前显示异常提示弹窗?
问题场景
在Android平台的MAUI项目中,我会先创建服务并加载数据,再将其注入到MauiApp中:
var myService=new(); myService.LoadData();// 此处可能抛出异常 var builder = MauiApp.CreateBuilder(); builder.Services.AddSingleton(myService);
部分服务加载数据时会抛出异常,当前异常会直接导致应用关闭且无任何提示信息。DisplayAlert仅能在Page中使用,但Page要等到App启动后才会创建。
在Xamarin中,我使用Android.App.AlertDialog.Builder结合Android.App.Application.Context可以正常显示异常弹窗,但在MAUI中除了Toast消息外,其他方式都会抛出如下异常:
Android.Views.WindowManagerBadTokenException: 'Unable to add window -- token null is not valid; is your activity running?'
App启动前Platform.CurrentActivity为null,想请教如何获取启动页上下文显示异常,或者有没有其他方式在应用启动前显示异常信息?
解决方案
方案1:捕获异常暂存,待Activity就绪后显示弹窗
核心思路是先捕获启动阶段的异常,暂存异常信息,等MainActivity初始化完成后再弹出提示框。
步骤1:在Program.cs中捕获异常并暂存
修改Program.cs的启动逻辑,捕获服务加载时的异常,同时保证应用能正常启动到Activity阶段:
using Microsoft.Maui; using Microsoft.Maui.Hosting; namespace YourAppNamespace; public static class Program { // 静态变量暂存启动异常 public static string? StartupException { get; private set; } [MauiProgram] public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); }); try { var myService = new MyService(); myService.LoadData(); builder.Services.AddSingleton(myService); } catch (Exception ex) { // 捕获异常并暂存 StartupException = ex.ToString(); // 添加空服务实例避免依赖注入报错 builder.Services.AddSingleton<MyService>(new MyService()); } return builder.Build(); } }
步骤2:在MainActivity中处理异常弹窗
打开Platforms/Android/MainActivity.cs,重写OnCreate方法,在Activity就绪后检查并显示异常弹窗:
using Android.App; using Android.Content.PM; using Android.OS; using AndroidX.AppCompat.App; namespace YourAppNamespace; [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); if (!string.IsNullOrEmpty(Program.StartupException)) { new AlertDialog.Builder(this) .SetTitle("启动失败") .SetMessage(Program.StartupException) .SetPositiveButton("退出", (sender, args) => Finish()) .SetCancelable(false) .Show(); } } }
方案2:延迟服务数据加载到App启动后
如果允许调整服务初始化时机,可以将数据加载逻辑延迟到App启动完成后,此时已经可以使用DisplayAlert:
修改服务类,添加延迟加载逻辑
public class MyService { public Exception? LoadException { get; private set; } public bool IsDataLoaded { get; private set; } public void LoadData() { try { // 原有的数据加载逻辑 // ... IsDataLoaded = true; } catch (Exception ex) { LoadException = ex; IsDataLoaded = false; } } }
在Program.cs中仅注册服务,不立即加载数据
[MauiProgram] public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); }); // 仅注册服务实例,不调用LoadData builder.Services.AddSingleton<MyService>(); return builder.Build(); }
在App.xaml.cs的OnStart中加载数据并处理异常
using Microsoft.Maui.Controls; namespace YourAppNamespace; public partial class App : Application { public App() { InitializeComponent(); MainPage = new MainPage(); } protected override void OnStart() { base.OnStart(); var myService = Services.GetRequiredService<MyService>(); myService.LoadData(); if (myService.LoadException != null) { MainPage.DisplayAlert("启动错误", myService.LoadException.Message, "确定"); // 可选:显示错误后退出应用 // Process.GetCurrentProcess().Kill(); } } }
方案3:使用Toast临时提示(简易方案)
如果不需要复杂的弹窗,仅需要简单提示,可以直接在捕获异常时调用Android的Toast:
catch (Exception ex) { // 仅在Android平台显示Toast #if ANDROID Android.Widget.Toast.MakeText(Android.App.Application.Context, $"启动错误:{ex.Message}", Android.Widget.ToastLength.Long).Show(); #endif // 后续逻辑... }
注意事项
- MAUI启动初期,
Platform.CurrentActivity为null,此时无法创建依赖Activity上下文的弹窗(如AlertDialog),必须等Activity的OnCreate方法执行完成后才能操作。 - 方案1的优势是可以在服务加载失败后仍让应用启动到Activity阶段,给用户明确的错误提示;方案2则更符合MAUI的生命周期规范,避免在启动阶段阻塞应用。
内容的提问来源于stack exchange,提问作者Виталий Соколов

