Как организовать длительные (отнимающие много времени) действия на Android?

StackOverflow https://stackoverflow.com/questions/2241049

  •  19-09-2019
  •  | 
  •  

Вопрос

Например, мы находимся в SomeActivity, и в activity есть кнопка, которая вызывает перемещение файлов из одного каталога в другой (давайте назовем это job).

На BlackBerry я бы:

  1. нажмите на всплывающее окно (Диалоговое окно), которое нельзя отменить, со словами "Пожалуйста, подождите ...".
  2. запустите поток, который выполняет задание
  3. по завершении потока закройте всплывающее окно

Такой подход на 99,99% может гарантировать, что мы останемся на том же экране после завершения задачи, пользователь просто увидит всплывающее окно и будет ждать завершения задания.Вращение устройства или что-то еще не нарушает желаемый рабочий процесс.

На Android все меняется.Я знаю, что есть AsyncTask, который, вероятно, предусмотрен для решения моего дела.Есть даже хороший пример о том, как его следует использовать.Но поскольку нет гарантии того, как долго будет жить экземпляр Activity, AsyncTask следует отменить в onSaveInstanceState (и перезапустить в onRestoreInstanceState).Это означает, что при использовании AsyncTask нет никакой гарантии, что мы сможем полностью выполнить задание после его запуска.В некоторых случаях при отправке http post-запроса для создания пользователя я бы не хотел получать сообщение "пользователь уже существует для этого входа" при повторном запуске AsyncTask.Это возможно, поскольку AsyncTask может быть прерван, когда запрос уже отправлен (и сервер фактически выполняет свою работу - создает нового пользователя), но AsyncTask отменяется до того, как мы получили ответ.

Есть ли какое-либо решение на Android для получения BB-подобного поведения, указанного выше?

Это было полезно?

Решение 3

В мае 2010 года Google выпустила новый сеанс ввода-вывода под названием Разработка клиентских приложений Android REST это объясняет, как достичь именно того, о чем я просил.

Оказалось, что вопрос довольно сложный, поэтому простого и быстрого решения не существует.Решение требует глубоких знаний платформы / API Android.Это цена, обусловленная гибкостью жизненного цикла процесса приложения / Активности.

Я чувствую некоторую странность в том, почему эта информация не была представлена с самой первой версии Android.Похоже, Google знала, как писать приложения без ошибок на 100%, но по каким-то маркетинговым причинам не разделяла этот подход.Только представьте, сколько глючных приложений было написано к маю 2010 года.

В любом случае, я рад, что теперь у меня есть то, что мы называем подходом наилучшей практики.

Другие советы

Но поскольку нет никакой гарантии того, как долго экземпляр деятельности будет жить, асинктаска должна быть отменена в OnsaveInstanceTate (и перезапустится на OnRestoreInstancestate).

Или им будет управлять Service.

Если ваша активность хочет оставаться на экране, вы можете просто запустить поток следующим образом:

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

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

Таким образом, GUI-Thread готов выполнять другие задачи, например, отображать

  android.app.ProgressDialog

Также рассмотрите возможность сделать диалог неотменяемым с помощью

  ProgressDialog.setCancelable(false);

Таким образом, пользователь может выйти только с помощью клавиши HOME, о которой вы получите уведомление, когда

  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();

Конечно, вам также придется отключить WakeLock, когда пользователь уходит с помощью клавиши HOME.

Наконец, если вы хотите вызвать GUI-Elements из своего фонового потока, это будет работать только в том случае, если поток является частью GUI-Event-Loop, как и обычный поток, в котором вы работаете, при вызове on... -Методы.Для этого ваш фоновый поток должен будет выполнить обратный вызов GUI-потока через обработчик.Так:

  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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top