为什么在显示 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"。这也有助于延长电池寿命。