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
}
Каковы преимущества/недостатки?
Edit:
Я не ищу ответов, таких как "легче увидеть код", "удобный для разработчиков" и т.д.
Я действительно ищу технические различия за сценой.
Например, Павел Никонович ответил ниже, это был ответ, который я хотел увидеть. (Но AsyncTask ведет себя одинаково)
Ответы
Ответ 1
Когда вы используете new Thread
, вы создаете новый поток каждый раз, когда выполняете это. AsyncTask
, однако, использует статический пул максимум 128 потоков и будет использовать старый поток всякий раз, когда он существует. Таким образом, запуск AsyncTask 10 раз в серийном режиме будет создавать только один поток, который запускает задачу 10 раз вместо 10 потоков.
Это одно из различий среди многих.
Ответ 2
Это удобство, по существу. Структура AsyncTask
связана с управлением пулом Thread
и обеспечивает простой, понятный интерфейс. Хорошо известно - тем, кто знает, как использовать AsyncTask
, что активность пользовательского интерфейса может продолжаться в onPreExecute()
, onPostExecute()
и onProgressUpdate()
и что весь "тяжелый подъем" выполняется в doInBackground()
, где вы не можете коснуться пользовательского интерфейса.
Это упрощает разработку разработчиком простой фоновой задачи, которая может легко публиковать обновления в потоке пользовательского интерфейса и возвращать результаты по завершении. Это не волшебство, это просто удобство.
Ответ 3
Согласно this, AsyncTask
проще в использовании, но имеет некоторые ограничения, такие как:
- Размер основного пула и рабочая очередь фиксированы: 5 пулов /10 элементов
- он жестко закодирован и не может быть изменен
- Приоритет нити фиксирован на низкий
- Обработка исключений не поддерживается так же, как с помощью
Thread
Также будет другая разница, которую я не понял.
Вы можете найти и проверить полный исходный код AsyncTask, поскольку Android является открытым исходным кодом: -)
Хорошо провести время с кодированием в Android!
Ответ 4
Основной недостаток заключается в том, что использование вашей собственной нити будет поддерживать активность в действии при вызове завершения. Android предоставит вам время для всех ваших потоков. Это приводит к возникновению утечки активности, которая в конечном итоге заставит ваше приложение работать очень медленно до тех пор, пока ваше приложение не перестанет работать с пользователем или операционной системой.
Вы можете проверить это, посмотрев ваш процесс в АБР. Даже когда деятельность завершена, вы все равно увидите, что она висит там, занимая ресурсы.
Итак, если вы используете свой собственный поток, убедитесь, что вы его управляете. Или просто используйте андроид-апи. Выбор ваш.
Ответ 5
Это ОЧЕНЬ разные.
- Первое взаимодействие с пользователем выполняется на основном потоке, а также на всех графических функциях.
- Второй
AsyncTask
предназначен для коротких всплесков выделенной активности, таких как загрузка файла или загрузка некоторых данных.
- В-третьих, поскольку все пользовательские интерфейсы и пользовательские взаимодействия выполняются в основном потоке, если вы начнете толкать материал в этот поток, устройство будет отставать и меньше реагировать на команды пользователя.
Единственная причина, по которой вы хотите запустить что-то в потоке пользовательского интерфейса, - это взаимодействие с виджетами. Кроме этого, если вы хотите выполнить длительную обработку, используйте AsyncTask
.
Edit:
Вы можете загружать свои данные в отдельный поток, и у меня нет никаких проблем с этим. Проблема возникает, когда вы хотите обновить интерфейс. В одиночку невозможно изменить пользовательский интерфейс из дочернего потока. Вместо этого вам придется создать либо обработчик, связанный с потоком пользовательского интерфейса, либо создать новый поток, который предназначен для запуска в потоке пользовательского интерфейса (как в вашем примере). Это не только утомительно, но и трагическая трата ресурсов. AsyncTask
позаботится об этом просто и эффективно.
Чтобы ответить на ваш последний вопрос, вы правы. AsyncTask
имеет доступ к основному потоку в pre/postExecute. Тем не менее, обработка (основной источник задержки UI), которую эта задача выполняет, не является. С помощью задачи пользовательский интерфейс будет влиять только на то, что вы рисуете, а не на то, чтобы ждать завершения задачи и любого ее чертежа.