为什么Xamarin.Forms中App.OnStart内await后设置MainPage无法加载主页面
问题根本原因
Xamarin.Forms框架底层的应用启动时序逻辑是导致该问题的核心原因:
- 各平台原生启动入口(Android的MainActivity、iOS的UIApplicationDelegate)完成Xamarin.Forms引擎初始化后,会先触发
Application类的OnStart方法,随后会立刻检查MainPage属性是否被赋值:- 如果已赋值,就将该页面对应的原生视图渲染到应用窗口
- 如果未赋值,原生层会直接加载一个空白的占位视图,且该占位视图加载完成后,框架默认不会再监听后续
MainPage的赋值事件做视图替换
async void修饰的OnStart方法遇到await关键字时,会立即返回调用方(也就是原生启动逻辑),此时你还没给MainPage赋值,原生层就会加载空白占位。等await任务执行完成回到后续代码时,再给MainPage赋值也不会触发原生视图的替换,所以看不到页面。- 没有await时,整个
OnStart方法是同步执行完成的,原生层检查MainPage时你已经完成赋值,所以可以正常渲染。
你判断的线程问题确实不成立,await Task.Delay(100)默认会捕获当前SynchronizationContext,后续代码确实运行在UI线程,和线程操作无关。
可行的解决方案
- 推荐方案:在
App的构造函数中先给MainPage赋值一个简单的闪屏页/加载占位页,等OnStart中的异步逻辑执行完成后,再替换MainPage为实际的业务首页,此时因为首次MainPage赋值已经完成,后续的替换操作会触发框架的视图更新逻辑,页面可以正常显示。
示例代码:public App() { InitializeComponent(); // 先设置临时加载页 MainPage = new ContentPage() { BackgroundColor = Color.White }; } protected override async void OnStart() { await Task.Delay(100); // 异步完成后替换为实际页面 MainPage = new Page(){ BackgroundColor = Color.Red }; } - 备选方案:如果确实不想提前设置临时页,也可以在异步结束赋值
MainPage后,手动调用平台原生层的窗口刷新逻辑,但该方案需要处理各平台的适配,兼容性不如推荐方案。
内容的提问来源于stack exchange,提问作者jordi casas
相关产品推荐
相关产品推荐

