Android: RunOnUiThread и AsyncTask

Я считаю, что Google предлагает разработчикам использовать AsyncTask. Однако я хотел бы знать, чем он отличается от использования "нового потока" и последующего вызова "RunOnUiThread" в плане производительности и эффективности использования памяти.

Пример использования RunOnUithread:

    // some code #1
    Thread t = new Thread("Thread1") {
        @Override
        public void run() {
            // some code #2
            runOnUiThread(new Runnable() {
                public void run() {
                    // some code #3 (that needs to be ran in UI thread)

                }
            });

        }
    };
    t.start();

против

AsyncTask:

onPreExecute() {
   // some code #1
}

doInBackground() {
   // some code #2
}

onPostExecute() {
   // some code #3
}

Каковы преимущества / недостатки?

Редактировать:

Я не ищу ответы типа "легче увидеть код", "удобно для разработчиков" и т. Д. Я на самом деле ищу технические различия за кулисами.

Например, ответ Пола Никоновича ниже был бы ответом, который я хотел увидеть. (Но AsyncTask ведет себя так же)

5 ответов

Решение

Когда вы используете new Thread вы действительно создаете новый поток каждый раз, когда выполняете это. AsyncTask однако, использует статический пул максимум 128 потоков и будет использовать старый поток всякий раз, когда он существует. Таким образом, запуск AsyncTask 10 раз в последовательном режиме создаст только один поток, который запускает задачу 10 раз вместо 10 потоков.

Это одно из различий среди многих.

По сути, это удобство. AsyncTask структура имеет дело с управлением Thread пул и обеспечивает простой, понятный интерфейс. Это хорошо известно - тем, кто умеет пользоваться AsyncTask - что пользовательский интерфейс может продолжаться в onPreExecute(), onPostExecute() а также onProgressUpdate()и что вся "тяжелая работа" выполняется в doInBackground() где вы не можете коснуться пользовательского интерфейса.

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

Согласно этому, AsyncTask проще в использовании, но имеет некоторые ограничения, такие как:

  • Размер основного пула и очередь работ фиксированы: 5 пулов / 10 элементов
    • это жестко закодировано и не может быть изменено
  • Приоритет потока установлен на низкий
  • Обработка исключений не так хорошо поддерживается, как с Thread

Также будет другое различие, которое я не понял. Вы можете найти и проверить полный исходный код AsyncTask, так как Android с открытым исходным кодом:-)

Приятного времяпровождения с кодированием в Android!

Основным недостатком является то, что использование собственного потока сохранит вашу активность при вызове Finish. Android даст вам время активности для завершения всех ваших тем. Это приводит к возникновению утечки активности, которая в конечном итоге приведет к тому, что ваше приложение будет работать очень медленно, пока ваше приложение не будет принудительно завершено ни пользователем, ни ОС.

Вы можете убедиться в этом, посмотрев на ваш процесс в АБР. Даже когда действие закончено, вы все равно увидите, что оно висит там, занимая ресурсы.

Так что, если вы используете свой собственный поток, убедитесь, что вы управляете этим. Или просто используйте Android-API. Выбор за вами.

Это очень по-разному.

  • Сначала ВСЕ пользовательское взаимодействие выполняется в основном потоке, а также все графические работы.
  • второй AsyncTask предназначен для коротких всплесков выделенной активности, такой как загрузка файла или загрузка некоторых данных.
  • В-третьих, поскольку все пользовательские интерфейсы и пользовательские взаимодействия выполняются в основном потоке, если вы начнете помещать данные в этот поток, устройство будет зависать и менее реагировать на команды пользователя.

Единственная причина, по которой вы хотите что-то запустить в потоке пользовательского интерфейса, - это взаимодействие с виджетами. Кроме этого, если вы хотите сделать длительную обработку, используйте AsyncTask,

Редактировать:

Вы можете загрузить свои данные в отдельной ветке, и у меня нет проблем с этим. Проблема возникает, когда вы хотите обновить пользовательский интерфейс. В одиночку невозможно изменить пользовательский интерфейс из дочернего потока. Вместо этого вам придется либо создать обработчик, связанный с потоком пользовательского интерфейса, либо создать новый поток, предназначенный для выполнения в потоке пользовательского интерфейса (как в вашем примере). Это не только утомительно, но и трагически трата ресурсов. AsyncTask позаботится об этом просто и эффективно.

Что касается вашего последнего пункта, вы правы. AsyncTask действительно имеет доступ к основному потоку в pre/postExecute. Однако обработка (основной источник задержки пользовательского интерфейса), которую выполняет задание, не выполняется. С заданием на пользовательский интерфейс будет влиять только то, что вы рисуете, в отличие от необходимости ждать, пока задание завершит свою работу, и какого бы рисунка он не хотел делать.

Другие вопросы по тегам