不知道大家感觉的到不,Xamarin.Forms生成的APP,在进行Page切换的时候,如果对应的页面的组件较多,总是感觉欠缺了点什么,明显的有点卡顿,尤其是在手机的配置较低的情况下。
笔者曾经考虑过,在构造函数的
InitializeComponent();
之前使用
Acr.UserDialogs.UserDialogs.Instance.ShowLoading("加载中");
之后再调用
Acr.UserDialogs.UserDialogs.Instance.HideLoading();
隐藏Loading。
但是悲剧的发现,UI根本没有出现Loading,还是跟原来一样,但是如果注释掉了InitializeComponent()这一行,改成休眠1秒钟,Loading就会正常的出现。但是只要InitializeComponent()方法被调用,都不会刷新UI。
期间做了很多的方法,都没有效果。
后来经过仔细的看了一下Xamarin的文档,终于找出问题的根源在哪里了。其实对于一个Page的生命周期,当进入一个Page之前,首先会调用构造函数,在构造函数中,会执行InitializeComponent()来绑定Xaml文件中的组件(这个绑定机制我没有深入研究)。在构造函数里面,Xamarin并不会时刻的刷新UI,避免压力过大。所以无论我们这个构造函数里面怎么去倒腾,都会需要等待。
当构造函数执行完成之后,就会加载OnAppearing()方法。在这两个方法之间,UI是会刷新的。所以说,我们把cs代码也没的结构做一下调整,问题就可以得到解决。
1、构造函数不再调用InitializeComponent()方法,里面只加上一句
Acr.UserDialogs.UserDialogs.Instance.ShowLoading("加载中");
2、在OnAppearing()方法修改为如下:
protected override void OnAppearing()
{
base.OnAppearing();
if (Content == null)
{
Device.StartTimer(TimeSpan.FromSeconds(0), () =>
{
InitializeComponent();
Refresh();
Acr.UserDialogs.UserDialogs.Instance.HideLoading();
return false;
});
return;
}
Refresh();
}
以上代码之所以加上Content == null的判断,主要是因为此方法再每次最小化、返回的时候都会被执行,加上可以避免重复执行InitializeComponent()方法。
经过以上调整,基本上点击按钮之后,就马上可以处理Loading的提示,加载完成之后,Loading会自动的隐藏。
但是这个也会造成一个问题,就是有时候我们需要在OnAppearing事件中做一些数据刷新的操作,就会产生Null报错的问题,具体的原因是由于我们异步的进行Xaml的初始化,再显示的时候,有可能该变量还没有初始化呢。所以应该将这些刷新的操作集成到一个方法Refresh()里面,并且刚方法应该在主线程中执行。