为什么在显示 AlertDialog 之前需要延迟?
Why do I need a delay before showing AlertDialog?
在某些情况下,当我的应用程序启动时,它会显示一个 AlertDialog。但是,永远不会显示警报。我发现如果我添加延迟,它会起作用(即显示)。
更具体地说:在应用程序启动时,它会执行主要的 activity onCreate(),在特定条件下会启动第二个 activity。在第二个 activity 中,它通过一个单独的线程检查某些 Web 服务器的状态。如果 Android 设备没有互联网连接,HttpURLConnection returns 会立即出错,我的封闭函数会执行对第二个 activity 的回调。然后我的代码使用 post() 尝试向用户显示警报(使用 post 允许在 UI 线程上显示警报,这是必需的)。
显然,它会尝试在 activity 的任何一个 UI 创建之前显示警报。如果我在第 2 个 activity 中使用 postDelayed(),问题仍然存在。但是,如果我在主 activity 中使用以下代码块,则警报会正确显示:
new Handler().postDelayed (new Runnable ()
{
@Override public void run()
{
Intent intent = new Intent (app, MyClass.class);
app.startActivityForResult (intent, requestCode);
}
}, 3000);
我的解决方案是一个恰好在此刻起作用的 hack。对于这种特殊情况,我不介意在启动时有一点延迟,但我不希望延迟时间超过必要时间或有时可能会失败。
什么是正确的解决方案?
好的,这里有一个解决方法。首先,我推测问题在于显示警报的尝试发生在 UI 线程的循环程序启动之前。只是猜测。
为了解决这个问题,我添加了一个从 onResume() 调用的递归 post,如下所示:
private boolean paused = true;
@Override public void onResume ()
{
super.onResume();
paused = false;
checkForAlert();
}
@Override public void onPause ()
{
super.onPause();
paused = true;
}
这是执行 post 的函数:
private AlertInfo alertInfo = null;
private void checkForAlert()
{
if (alertInfo != null)
{
...code to build alert goes here...
alertInfo = null;
}
if (!paused)
contentView.postDelayed (new Runnable()
{
@Override public void run() { checkForAlert(); }
}, 200);
}
AlertInfo 是一个简单的 class,需要警报的线程可以在其中放置相关信息,例如标题,留言。
那么,这是如何运作的? checkForAlert() 在 onResume() 期间被调用,并将继续每 200 毫秒被调用一次,直到 "paused" 为假,这发生在 onPause() 中。每当显示 activity 时,它保证会重复出现。如果 alertInfo 不为空,将构建并显示警报。在辅助线程中,我只是创建一个 AlertInfo 实例,然后在 200 毫秒内显示警报。 200ms 足够短,大多数人不会注意到延迟。它可能会更短,但随后电池使用量会增加。
为什么我在 onResume 中启动 checkForAlert() 而不是 onCreate()?只是因为没有必要 运行 除非 activity 当前是 "on top"。这也有助于延长电池寿命。
在某些情况下,当我的应用程序启动时,它会显示一个 AlertDialog。但是,永远不会显示警报。我发现如果我添加延迟,它会起作用(即显示)。
更具体地说:在应用程序启动时,它会执行主要的 activity onCreate(),在特定条件下会启动第二个 activity。在第二个 activity 中,它通过一个单独的线程检查某些 Web 服务器的状态。如果 Android 设备没有互联网连接,HttpURLConnection returns 会立即出错,我的封闭函数会执行对第二个 activity 的回调。然后我的代码使用 post() 尝试向用户显示警报(使用 post 允许在 UI 线程上显示警报,这是必需的)。
显然,它会尝试在 activity 的任何一个 UI 创建之前显示警报。如果我在第 2 个 activity 中使用 postDelayed(),问题仍然存在。但是,如果我在主 activity 中使用以下代码块,则警报会正确显示:
new Handler().postDelayed (new Runnable ()
{
@Override public void run()
{
Intent intent = new Intent (app, MyClass.class);
app.startActivityForResult (intent, requestCode);
}
}, 3000);
我的解决方案是一个恰好在此刻起作用的 hack。对于这种特殊情况,我不介意在启动时有一点延迟,但我不希望延迟时间超过必要时间或有时可能会失败。
什么是正确的解决方案?
好的,这里有一个解决方法。首先,我推测问题在于显示警报的尝试发生在 UI 线程的循环程序启动之前。只是猜测。
为了解决这个问题,我添加了一个从 onResume() 调用的递归 post,如下所示:
private boolean paused = true;
@Override public void onResume ()
{
super.onResume();
paused = false;
checkForAlert();
}
@Override public void onPause ()
{
super.onPause();
paused = true;
}
这是执行 post 的函数:
private AlertInfo alertInfo = null;
private void checkForAlert()
{
if (alertInfo != null)
{
...code to build alert goes here...
alertInfo = null;
}
if (!paused)
contentView.postDelayed (new Runnable()
{
@Override public void run() { checkForAlert(); }
}, 200);
}
AlertInfo 是一个简单的 class,需要警报的线程可以在其中放置相关信息,例如标题,留言。
那么,这是如何运作的? checkForAlert() 在 onResume() 期间被调用,并将继续每 200 毫秒被调用一次,直到 "paused" 为假,这发生在 onPause() 中。每当显示 activity 时,它保证会重复出现。如果 alertInfo 不为空,将构建并显示警报。在辅助线程中,我只是创建一个 AlertInfo 实例,然后在 200 毫秒内显示警报。 200ms 足够短,大多数人不会注意到延迟。它可能会更短,但随后电池使用量会增加。
为什么我在 onResume 中启动 checkForAlert() 而不是 onCreate()?只是因为没有必要 运行 除非 activity 当前是 "on top"。这也有助于延长电池寿命。