我在点击登录按钮后显示活动指示器,直到将用户重定向到另一个页面,让他们了解正在进行的一些进展。但点击登录按钮后,活动指示器不会立即显示,几秒钟后会显示,
为什么会这样?为了减少这种延迟,我只是把活动指标......
我的代码:
async void loginButtonGesture_Tapped(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
loadingPanel.IsRunning = true;
loadingPanel.IsVisible = true;
});
}
答案 0 :(得分:0)
该方法是否必须是异步无效的?似乎主线程上的这个特定调度不应该是异步的。试试看它是否会改变任何东西。您还可以尝试在Device.BeginInvokeOnMainThread行上设置断点,并尝试在loadingPanel.IsRunning ...行中查看延迟发生的位置。
答案 1 :(得分:0)
首先,loginButtonGesture_Tapped()事件处理程序由UI线程触发,因此您不需要使用Device.BeginInvokeOnMainThread(),它已经在UI线程中。但是因为你在这里使用了Device.BeginInvokeOnMainThread(),所以延迟的原因是因为在Android上,你的BeginInvokeOnMainThread()内的代码被添加到MainLooper的消息队列中,(你的代码没有立即执行)并被执行当UI线程被安排处理其消息时。
详细解答可以在Xamarin文档中找到:
对于iOS:
IOSPlatformServices.BeginInvokeOnMainThread()方法只调用NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
您可以从线程中使用此方法来调用UI线程中使用指定选择器公开的指定对象中的代码。 这对于影响UIKit或AppKit的大多数操作都是必需的,因为这些API中没有一个是线程安全的。
当主线程返回其主循环以处理事件时执行代码。
对于Android:
许多人认为Xamarin.Android的BeginInvokeOnMainThread()方法使用Activity.runOnUiThread(),但事实并非如此,并且使用runOnUiThread()和Handler.Post()之间存在差异:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
可以在AndroidPlatformServices.cs类中找到Xamarin.Android BeginInvokeOnMainThread()方法的实际实现
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable) 如您所见,Handler.Post(操作)不会立即执行操作代码。它被添加到Looper的消息队列中,并在UI线程被安排处理其消息时被处理。