如何在Android上安排长时间(耗时)的操作?

时间:2010-02-10 23:12:53

标签: android android-asynctask

例如,我们在SomeActivity中,并且活动有一个按钮,用于调用从一个目录到另一个目录的移动文件(让我们称之为作业)。

在BlackBerry上我会:

  1. 按下一个不可取消的弹出窗口(对话框屏幕),说“请稍候......”
  2. 启动一个完成工作的线程
  3. 在线程完成时关闭弹出窗口
  4. 这种方法99.99%可以保证我们在任务结束后保持在同一个屏幕上,用户只需看到弹出窗口并等待作业完成。设备轮换或任何不会破坏所需工作流程的内容。

    在Android上的事情发生了变化。我知道可能提供了AsyncTask来解决我的问题。它应该如何使用example。但由于无法保证Activity实例的存在时间,因此应在onSaveInstanceState上取消AsyncTask(并在onRestoreInstanceState上重新启动)。这意味着使用AsyncTask并不能保证我们能够在启动后完全完成工作。在某些情况下,当发送用于创建用户的http post请求时,我不希望在重新运行AsyncTask时遇到“用户已存在此登录”的麻烦。这是可能的,因为AsyncTask可以在请求已经发送时被中断(并且服务器实际上正在完成它的工作 - 创建一个新用户),但在我们得到响应之前取消了AsyncTask。

    Android上是否有任何解决方案可以获得上述类似BB的行为?

3 个答案:

答案 0 :(得分:2)

  

但是因为不能保证如何   一个Activity实例将存活   应该取消AsyncTask   onSaveInstanceState(并重新启动   onRestoreInstanceState)。

或者让它由Service管理。

答案 1 :(得分:1)

如果你的活动希望留在屏幕上,你可以简单地启动一个这样的线程:

final File fromFile = ...;
final File toFile = ...;

new Thread() {
    @Override
    public void run() {
      // do something with fromFile, toFile
    }
}.start();

这样GUI-Thread就可以做其他想法了,就像显示

一样
  android.app.ProgressDialog

另外,请考虑使用

使Dialog无法解决
  ProgressDialog.setCancelable(false);

这样,用户只能通过HOME-Key离开,您将收到

的通知
  Activity.onPause()

被调用。此外,您可能需要查看Wakelocks,以阻止屏幕变黑,并将应用程序推入可能被杀死的背景中。你可以在线程中执行此操作:

  PowerManager pm = (PowerManager) ivContext.getSystemService(Context.POWER_SERVICE);
  Wakelock wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MyApp");
  wakeLock.acquire();

  // ... copy stuff ...

  wakeLock.release();

当用户通过HOME-Key离开时,你必须释放wakeLock。

最后,如果你想从后台线程中调用GUI-Elements,这只有在Thread是GUI-Event-Loop的一部分时才有效,就像正在运行的普通线程一样,当被调用时...-方法。要实现这一点,您的后台线程必须通过Handler回调GUI-Thread。像这样:

  private Handler mHandler = new Handler() { 
      @Override
      public void handleMessage(Message msg) {
          Log.v(TAG, "Got Message "+msg.what); // prints: Got Message 77
      // ... do GUI actions ...
      }    
  };

  // ... in Thread ...

  int lvInfo = 77;
  mHandler.sendEmptyMessage(lvInfo);

您甚至可以在邮件中放置对象:

  Message txtMsg = Message.obtain();
  textMsg.obj = "Hello World";
  mHandler.sendMessage(lvTextMsg);

答案 2 :(得分:0)

2010年5月,Google发布了一个名为Developing Android REST client applications的新IO会话,解释了如何实现我的要求。

事实证明这个问题相当复杂,因此没有简单快捷的解决方案。该解决方案需要深入了解Android平台/ API。这是由应用程序进程/活动生命周期的灵活性引起的价格。

我觉得为什么这个信息没有从Android的第一个版本中呈现出来有些奇怪。看起来Google知道如何编写100%无bug的应用程序,并且由于某些营销原因没有分享这种方法。想象一下2010年5月写了多少个错误的应用程序。

无论如何,我很高兴现在我称之为最佳实践方法。