Handler vs AsyncTask vs Thread [закрито]


382

Я отримав трохи збентежений про відмінності між Handlers, AsyncTaskі Threadsв Android. Я прочитав досить багато блогів та запитань тут у StackOverflow.

Handler- фонові потоки, які надають вам змогу спілкуватися з інтерфейсом користувача. Наприклад, оновлення рядка прогресу повинно бути здійснено через Handler. Використовуючи обробники, ви маєте перевагу MessagingQueues, тому якщо ви хочете запланувати повідомлення або оновити кілька елементів інтерфейсу або мати завдання, що повторюються.

AsyncTaskнасправді вони подібні, вони використовують Handler, але не працюють в потоці інтерфейсу, тому це добре для отримання даних, наприклад, отримання веб-служб. Пізніше ви можете взаємодіяти з інтерфейсом користувача.

Threadоднак не може взаємодіяти з користувальницьким інтерфейсом, надавати більш "базові" нарізки, і ви пропускаєте всі абстракції AsyncTask.

Однак я хотів би, щоб у роботі було встановлено з'єднання з розеткою. Чи слід це запускати в обробнику чи потоці, а то й у AsyncTask? Взаємодія інтерфейсу взагалі не потрібна. Чи має значення зміна продуктивності, яку я використовую?

Тим часом документація значно покращилась.



9
"Обробники - це фонові нитки". Здається, деякі відповіді з голосовими відгуками також йдуть у цьому напрямку. Але це неправильне уявлення. A Handlerне є потоком, і він нічого не виконує. Це лише засіб безпечно передавати повідомлення з однієї нитки до черги повідомлень іншої нитки . Отже, як правило, повинні бути створені (принаймні) два потоки, які потім можуть використовувати обробник, але обробник нічого не може виконати сам.
JimmyB

Відповіді:


57

Як підручник по обробці фону Android з обробниками, AsyncTask та навантажувачами на сайті Vogella:

HandlerКлас може бути використаний для реєстрації в тему і забезпечує простий канал для передачі даних на цю тему.

AsyncTaskКлас инкапсулирует створення фонового процесу і синхронізацію з основним потоком. Він також підтримує звітність про хід виконання завдань.

А в Threadосновному є основним елементом багатопотокової роботи, який розробник може використовувати із наступним недоліком:

Якщо ви використовуєте потоки Java, у власному коді потрібно обробити такі вимоги:

  • Синхронізація з основним потоком, якщо ви опублікували результати в інтерфейсі користувача
  • Немає за замовчуванням для скасування потоку
  • Немає об'єднання ниток за замовчуванням
  • Немає за замовчуванням для обробки змін конфігурації в Android

І стосовно AsyncTask, як до Посібнику Android Developer :

AsyncTaskдозволяє правильно та легко користуватися потоком інтерфейсу користувача. Цей клас дозволяє виконувати фонові операції та публікувати результати в потоці інтерфейсу користувача, не маніпулюючи потоками та / або обробниками.

AsyncTaskрозроблений для того, щоб бути помічником класу навколо ThreadтаHandler не є загальною рамкою для різьблення. AsyncTasks в ідеалі слід використовувати для коротких операцій (максимум за кілька секунд.) Якщо вам потрібно тримати потоки протягом тривалих періодів часу, настійно рекомендується використовувати різні API, надані пакетом java.util.concurrent, наприклад Виконавець, ThreadPoolExecutor та FutureTask.

Оновлення травня 2015 року: я знайшов чудову серію лекцій, що висвітлювали цю тему.

Це пошук у Google: Дуглас Шмідт, лекція про паралельність та синхронізацію Android

Це відео першої лекції на YouTube

Все це є частиною CS 282 (2013): Системне програмування для Android від університету Вандербільта . Ось список відтворення YouTube

Дуглас Шмідт, здається, відмінний викладач

Важливо: Якщо ви перебуваєте в точці, де ви плануєте використовувати AsyncTaskдля вирішення своїх проблем з ниткою, спочатку слід ознайомитися зReactiveX/RxAndroid можливою більш відповідною схемою програмування. Дуже хороший ресурс для отримання огляду - це вивчення RxJava 2 для Android на прикладі .


4
У цій серії лекцій це посилання переведе вас до декількох прикладів теми
Агресор

353

Якщо ми подивимось на вихідний код, то побачимо AsyncTaskі Handlerчисто написаний на Java. (Однак є деякі винятки. Але це не важливий момент)

Так що в магії немає AsyncTaskчи Handler. Ці класи полегшують наше життя як розробника.

Наприклад: Якщо програма A викликає метод A (), метод A () може запускатися в інший потік із програмою A. Ми можемо легко перевірити наступним кодом:

Thread t = Thread.currentThread();    
int id = t.getId();

Чому ми повинні використовувати нову нитку для деяких завдань? Ви можете використовувати Google для цього. Багато причин, наприклад: важкий підйом, тривалі роботи.

Отже, які відмінності між Thread, AsyncTaskі Handler?

AsyncTaskі Handlerнаписані на Java (внутрішньо вони використовують a Thread), тому все, що ми можемо зробити, Handlerабо AsyncTaskми також можемо досягти, використовуючи Threadтакож.

Що може Handlerі AsyncTaskсправді допомогти?

Найбільш очевидна причина - це зв'язок між потоком абонента та робочою ниткою. ( Calle Thread : Потік, який викликає Worker Thread для виконання деяких завдань. Потік абонента не обов'язково повинен бути потоком UI). Звичайно, ми можемо спілкуватися між двома потоками іншими способами, але є багато недоліків (і небезпек) через безпеку ниток.

Ось чому ми повинні використовувати Handlerі AsyncTask. Ці класи роблять більшу частину роботи для нас, нам потрібно лише знати, які методи перекрити.

Різниця між Handlerта AsyncTaskє: Використовуйте, AsyncTaskколи потік Caller - це нитка інтерфейсу користувача . Про це говорить документ Android:

AsyncTask забезпечує правильне та просте використання потоку інтерфейсу користувача. Цей клас дозволяє виконувати фонові операції та публікувати результати в потоці інтерфейсу користувача, не маніпулюючи потоками та / або обробниками

Хочу підкреслити два моменти:

1) Легке використання потоку користувальницького інтерфейсу (так, використовуйте, коли потоком виклику є нитка UI).

2) Не потрібно маніпулювати обробниками. (означає: Ви можете використовувати Handler замість AsyncTask, але AsyncTask - простіший варіант).

У цій публікації є багато речей, про які я ще не говорив, наприклад: що таке UI Thread або чому це простіше. Ви повинні знати деякі методи, що стоять за кожним класом, і використовувати його, ви повністю зрозумієте причину.

@: прочитавши документ Android, ви побачите:

Обробник дозволяє надсилати та обробляти об'єкти повідомлення та запуску, пов'язані з повідомленнями

Цей опис може здатися дивним спочатку. Нам потрібно лише зрозуміти, що кожен потік має кожну чергу повідомлень (як список справ), і потік прийме кожне повідомлення і виконуватиме це, поки черга повідомлень не буде порожньою (так само, як ми закінчимо свою роботу і ляжемо спати). Тому, колиHandler спілкуєтесь, він просто дає повідомлення потоці абонента, і він буде чекати, щоб обробити.

Складні? Просто пам’ятайте, що Handlerможете безпечно спілкуватися з потоком абонента.


4
насправді asynctask також заснований на обробниках і futuretask, див.
Суміт

AsyncTask - це, по суті, клас помічників, побудований на версії Handler and Thread. developer.android.com/reference/android/os/AsyncTask.html . Подивіться на документ "AsyncTask розроблений таким чином, щоб він допомагав класу навколо теми та обробника". AsyncTask випускається в API3, тоді як Handler існує з API1.
hjchin

52

Подивившись поглиблено, прямо вперед.

AsyncTask:

Це простий спосіб використовувати нитку, нічого не знаючи про модель ниток java . AsyncTaskнадає різні зворотні дзвінки відповідно до робочої нитки та основної нитки.

Використовуйте для невеликих операцій очікування, таких як:

  1. Отримання деяких даних із веб-служб та відображення у макеті.
  2. Запит на базу даних.
  3. Коли ви зрозумієте, що запущена операція ніколи не буде вкладеною.

Handler:

Коли ми встановлюємо додаток в android, тоді він створює нитку для цієї програми під назвою MAIN UI Thread. Усі дії проводяться всередині цієї теми. За правилом моделі єдиного потоку для Android, ми не можемо отримати доступ до елементів інтерфейсу користувача (растрового зображення, перегляду тексту тощо) безпосередньо для іншого потоку, визначеного всередині цієї діяльності.

Обробник дозволяє вам спілкуватися з потоком інтерфейсу користувача з інших фонових потоків. Це корисно в android, оскільки android не дозволяє іншим потокам спілкуватися безпосередньо з потоком інтерфейсу користувача. Обробник може надсилати та обробляти об'єкти повідомлення та запуску, пов'язані з повідомленнями. Кожен екземпляр обробника асоціюється з одним потоком і чергою повідомлення цього потоку. Коли створюється новий обробник, він прив'язується до черги потоку / повідомлення потоку, який його створює.

Це найкраще підходить для:

  1. Це дозволяє робити чергу з повідомленнями.
  2. Планування повідомлень.

Thread:

Тепер настав час поговорити про нитку.

Нитка є батьком обох AsyncTaskта Handler. Вони обидва використовують внутрішній потік, а це означає, що ви також можете створити власну модель потоку на зразок AsyncTaskта Handler, але це вимагає хороших знань щодо багаторівневої реалізації Java .


1
Фактично, AsyncTask api написано разом із Futures, Handlers та Executor. Дивіться вихідний код: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgorGanapolsky

22

AsyncTaskВикористовується , щоб зробити деякі базові обчислення і опублікувати результат в потоці призначеного для користувача інтерфейсу (з додатковими оновленнями прогресу). Оскільки ви не переймаєтесь користувальницьким інтерфейсом, то такий Handlerабо Threadздається більш підходящим.

Ви можете створити фон Threadі передати повідомлення назад в основний потік, використовуючи метод Handler's post.


9

Нитка

Android підтримує стандартні потоки Java . Ви можете використовувати стандартні нитки та інструменти з пакету " java.util.concurrent", щоб розмістити дії на задньому плані. Єдине обмеження полягає в тому, що ви не можете безпосередньо оновити інтерфейс користувача у фоновому процесі.

Якщо вам потрібно оновити інтерфейс користувача з фонового завдання, вам потрібно використовувати деякі специфічні для Android класи. Ви можете використовувати клас " android.os.Handler" для цього або клас " AsyncTask"

Обробник

Клас " Handler" може оновити інтерфейс користувача. Ручка забезпечує способи прийому повідомлень та для запуску. Щоб використовувати обробник, ви повинні підкласифікувати його та замінити handleMessage()обробку повідомлень. Для обробки Runableможна скористатися методом. post();У вашій діяльності потрібен лише один екземпляр обробника.

Ви нитка може відправляти повідомлення з допомогою методу sendMessage(Message msg)або sendEmptyMessage.

AsyncTask

Якщо у вас є Activityнеобхідність завантажувати вміст або виконувати операції, які можна виконати у фоновому режимі, AsyncTaskви можете підтримувати чуйний користувальницький інтерфейс і публікувати хід цих операцій користувачеві.

Для отримання додаткової інформації ви можете ознайомитися з цими посиланнями.

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


6

Thread:

Ви можете використовувати нове Threadдля тривалих фонових завдань, не впливаючи на нитку інтерфейсу користувача. З теми Java Thread, ви не можете оновити UI Thread.

Оскільки звичайна нитка не дуже корисна для архітектури Android, були запроваджені допоміжні класи для нитки.

Ви можете знайти відповіді на свої запити на сторінці документації щодо продуктивності теми .

Обробник :

A Handlerдозволяє надсилати та обробляти Повідомлення та Runnableоб'єкти, пов'язані з потоком MessageQueue. Кожен Handlerекземпляр асоціюється з одним потоком і чергою повідомлення цього потоку.

Існує два основних напрямки використання Handler:

  1. Запланувати повідомлення та запущені повідомлення як певний момент у майбутньому;

  2. Запропонувати дії, які слід виконати в іншій темі, ніж ваша власна.

AsyncTask :

AsyncTaskдозволяє правильно та легко користуватися потоком інтерфейсу користувача. Цей клас дозволяє виконувати фонові операції та публікувати результати в потоці інтерфейсу користувача, не маніпулюючи потоками та / або обробниками.

Недоліки:

  1. За замовчуванням додаток натискає всі AsyncTask об'єкти, які він створює, в одну нитку. Тому вони виконуються послідовно, і - як і в основному потоці - особливо довгий робочий пакет може блокувати чергу. З цієї причини використовуйте AsyncTask для обробки робочих предметів тривалістю менше 5 мс .

  2. AsyncTaskоб'єкти також є найпоширенішими правопорушниками для неявних посилань. AsyncTaskоб'єкти також представляють ризики, пов'язані з явними посиланнями.

HandlerTread :

Можливо, вам знадобиться більш традиційний підхід до виконання блоку роботи над тривалою ниткою ( на відміну від AsyncTask, який слід використовувати для навантаження 5 мс ), а також певна здатність керувати цим робочим процесом вручну. Нитка обробника - це фактично довга нитка, яка захоплює роботу з черги та працює на ній.

ThreadPoolExecutor :

Цей клас керує створенням групи потоків, встановлює їхні пріоритети та керує розподілом роботи між цими потоками. У міру збільшення або зменшення навантаження робочий клас розкручується або знищує більше ниток, щоб підлаштовуватися під навантаження.

Якщо навантаження більше, а одиночних HandlerThreadне вистачає, можна продовжуватиThreadPoolExecutor

Однак я хотів би, щоб у мережі працювало з'єднання з розеткою. Чи слід це запускати в обробці або потоці, або навіть AsyncTask? Взаємодія інтерфейсу взагалі не потрібна. Чи має значення зміна продуктивності, яку я використовую?

Оскільки взаємодія з інтерфейсом користувача не потрібна, ви можете не користуватися цим AsyncTask. Звичайні нитки не дуже корисні, а значить HandlerThread, найкращий варіант. Оскільки вам доведеться підтримувати з'єднання з гніздом, обробник на головній нитці зовсім не корисний. Створіть HandlerThreadі отримайте Handlerз петлі HandlerThread.

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

Якщо ви хочете повернутися до потоку інтерфейсу, ви можете використовувати ще один обробник для обробки відповіді.

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

у своєму Runnable, ви можете додати

responseHandler.sendMessage(msg);

Детальніше про реалізацію можна знайти тут:

Android: Тост в нитці


5

На мою думку, потоки - це не найефективніший спосіб підключення сокетів, але вони забезпечують найбільшу функціональність з точки зору запуску потоків. Я кажу, що через досвід тривалий час запуску ниток призводить до того, що пристрої дуже гарячі та ресурсомісткі. Навіть простий while(true)нагріє телефон за лічені хвилини. Якщо ви говорите, що взаємодія із користувальницьким інтерфейсом не важлива, можливоAsyncTask це добре, оскільки вони розроблені для довготривалих процесів. Це лише моя думка щодо цього.

ОНОВЛЕННЯ

Будь ласка, ігноруйте мою вище відповідь!Я відповів на це запитання ще в 2011 році, коли я був набагато менш досвідчений в Android, ніж зараз. Моя відповідь вище є оманливою і вважається неправильною. Я залишаю його там, тому що багато людей коментують це нижче, виправляючи мене, і я засвоїв свій урок.

На цю тему є набагато кращі відповіді, але я принаймні дам більш правильну відповідь. Немає нічого поганого у використанні звичайної Java Thread; однак, ви повинні бути дуже обережними щодо того, як це реалізувати, тому що робити це неправильно може дуже інтенсивно процесор (найбільш помітним симптомом може бути нагрівання вашого пристрою). AsyncTasks досить ідеально підходить для більшості завдань, які ви хочете виконувати у фоновому режимі (поширеними прикладами є введення / виведення диска, мережеві дзвінки та дзвінки до бази даних). Однак AsyncTasks не слід використовувати для особливо тривалих процесів, які можуть знадобитися продовжити після того, як користувач закриє вашу програму або переведе свій пристрій у режим очікування. Я б сказав, що в більшості випадків все, що не належить до потоку користувальницького інтерфейсу, може бути вирішено в anAsyncTask .


дякую, чи є насправді причина, чому я повинен використовувати теми замість AsyncTasks? Або рекомендується скоріше використовувати його?
Алкс

9
@AeroDroid У вашому прикладі: "простий час (правда)", ви будете прив’язувати до цього процесор, якщо ви не додасте стан циклу сну в циклі. Це стосується будь-якого нескінченного циклу. Якщо ви хочете зменшити використання процесора через цю накладну, спайте нитку на кілька мілісекунд у кінці циклу.
Помилка 454,

1
@Error 454 - це цікаво! Якби вам довелося вибрати відповідне число для часу сну, чи не було б це 40-80 мілісекунд?
Абхіджіт

6
@Abhijit З ігрових речей, які я робив у SDL, просто додавання сну в 10 мс до циклу було достатньо, щоб знизитись з 99% процесора до ~ 0 під час роботи в режимі очікування.
Помилка 454

15
Насправді developer.android.com/reference/android/os/AsyncTask.html говорить: "AsyncTasks в ідеалі слід використовувати для коротких операцій". Ви також повинні їх обережно використовувати, оскільки система може бути відхилена без виконання!
type-a1pha

5

AsyncTaskпризначений для виконання не більше декількох секунд операцій, які потрібно виконати у фоновому режимі (не рекомендується для завантаження мегабайт файлів з сервера або обчислювальних процесорів, таких як операції з виведенням файлів). Якщо вам потрібно виконати тривалу операцію, вам настійно рекомендується використовувати рідні теми Java. Java надає різні класи, пов'язані з потоками, щоб робити те, що потрібно. Використовуйте Handlerдля оновлення потоку інтерфейсу користувача.


2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

1

Дозвольте спробувати відповісти на питання на прикладі :) - MyImageSearch [Будь ласка, відправте зображення тут на головному екрані діяльності - містить текст редагування / кнопку пошуку / сітку]

MyImageSearch

Опис MyImageSearch - Після того, як користувач введе реквізити в текстове поле редагування та натисне кнопку пошуку, ми будемо шукати зображення в Інтернеті через веб-сервіси, надані flickr (вам потрібно зареєструватися там, щоб отримати ключ / секретний маркер) - для пошуку ми повертаємо запит HTTP та повертаємо дані JSON у відповідь, що містить URL-адреси окремих зображень, які ми використаємо для завантаження представлення сітки.

Моя реалізація - в основній діяльності я визначу внутрішній клас, який розширює AsyncTask, щоб надіслати запит HTTP методом doInBackGround та отримати відповідь JSON та оновити мій локальний ArrayList of FlickrItems, який я буду використовувати для оновлення свого GridView через FlickrAdapter (розширює BaseAdapter) і зателефонуйте adapter.notifyDataSetChanged () в onPostExecute () AsyncTask, щоб перезавантажити вигляд сітки. Зауважте, що тут Запит HTTP - це виклик блокування, через який я це зробив через AsyncTask. І я можу кешувати елементи в адаптері для підвищення продуктивності або зберігати їх на SDCard. Сітка, яку я надуваю у FlickrAdapter, містить у моїй реалізації панель прогресу та зображення. Нижче ви знайдете код для mainActivity, який я використав.

Відповідь на питання зараз - Отже, коли ми отримаємо дані JSON для отримання окремих зображень, ми зможемо реалізувати логіку отримання зображень у фоновому режимі через обробники або нитки або AsyncTask. Тут слід зазначити, що оскільки мої зображення, щойно завантажені, повинні відображатися в інтерфейсі / головному потоці, ми не можемо просто використовувати нитки, як це є, оскільки вони не мають доступу до контексту. У FlickrAdapter можливі варіанти:

  • Вибір 1: Створіть LooperThread [розширює потік] - і продовжуйте завантажувати зображення послідовно в одному потоці, зберігаючи цю нитку відкритою [looper.loop ()]
  • Вибір 2: Скористайтеся потоковим пулом та опублікуйте запуск через myHandler, який містить посилання на мій ImageView, але оскільки перегляди в Grid View переробляються, знову може виникнути проблема, коли зображення в індексі 4 відображається в індексі 9 [завантаження може займати більше часу]
  • Вибір 3 [Я використав це]: Скористайтеся пулом ниток і надішліть повідомлення моєму Handler, яке містить дані, пов’язані з індексом ImageView та самим ImageView, тому, виконуючи handMessage (), ми будемо оновлювати ImageView лише у тому випадку, якщо currentIndex відповідає індексу Зображення, яке ми намагалися завантажити.
  • Вибір 4: Використовуйте AsyncTask для завантаження зображень у фоновому режимі, але тут я не матиму доступу до кількості потрібних потоків у пулі потоків, і це змінюється в різних версіях для Android, але у Choice 3 я можу приймати свідоме рішення розміру пулу потоку в залежності від конфігурації пристрою, що використовується.

Ось вихідний код:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Я сподіваюся, що моя відповідь, хоча довго, допоможе розібратися в деяких тонких деталях.


Чи можу я знати причину того, чому моє пояснення на основі прикладу аналогії було знято з голосу, щоб я також дізнався з нього?
аккшаймані

2
насамперед дякую за вашу відповідь, хоча ця тема трохи стара, основні поняття залишаються актуальними. На моє початкове запитання взагалі не відповідають, ви наводите приклад і пояснюєте, як воно працює, але запитання задають відмінності між обробником, асинтактом і потоком.
Алкс

@ 80leaves гаразд, я зараз зрозумів, я спробував пояснити, як я прийшов до висновку про вибір одного шляху над іншим. У будь-якому разі, я хотів би почути ваші / інші погляди на те, чи те, що я написав, є правильним, чи його можна вдосконалити далі.
акшаймані

1

Залежить від того, який вибрати, виходячи з вимоги

Обробник в основному використовується для переходу з іншої нитки на основну нитку, Хендлер прикріплений до петлі, на якому він розміщує в черзі своє виконання завдання. Отже, якщо ви вже в іншому потоці та переходите на основний потік, тоді вам потрібно обробляти замість завдання async чи іншого потоку

Якщо обробник, створений за винятком основної нитки, яка не є петлею, не помилиться, оскільки ручка створена ниткою, її потрібно зробити петелькою

AsyncTask використовується для виконання коду протягом декількох секунд, який працює на фоновому потоці і дає його результат головному потоку ** * Обмеження AsyncTask 1. Завдання Async не приєднано до життєвого циклу діяльності, і воно продовжує працювати, навіть якщо його діяльність знищена, тоді як завантажувач не робить у цього обмеження немає. Усі завдання Async мають однакові фонові нитки для виконання, які також впливають на продуктивність програми

Thread використовується також у додатку для фонової роботи, але у ній немає зворотного дзвінка на основній темі. Якщо вимога відповідає одному потоку замість одного потоку і якому потрібно давати завдання багато разів, тоді кращим варіантом є виконавець пулу потоків. Наприклад, вимога завантаження зображення з декількох URL-адрес, таких як glide.


0

Нитка

Коли ви запускаєте додаток, створюється процес для виконання коду. Для ефективного використання обчислювального ресурсу потоки можна запускати в процесі, щоб одночасно можна було виконати кілька завдань. Таким чином, потоки дозволяють створювати ефективні додатки, ефективно використовуючи процесор без простою.

В Android всі компоненти виконуються на одній, що називається головною темою. Завдання системної черги Android та виконайте їх по черзі в основному потоці. Коли тривалі завдання виконуються, додаток не відповідає.

Щоб цього не допустити, можна створити робочі потоки та виконувати фонові чи тривалі завдання.

Обробник

Оскільки андроїд використовує модель однопотокових, компоненти інтерфейсу створюються безпотоково безпечно, тобто лише створений ним потік повинен мати доступ до них, що означає, що компонент інтерфейсу повинен оновлюватися лише на головному потоці. Оскільки компонент інтерфейсу працює на головному потоці, завдання, які виконуються на робочих потоках, не можуть змінювати компоненти інтерфейсу. Тут описується Хендлер. Обробник за допомогою Looper може з'єднатися з новою ниткою або існуючим потоком і запустити код, який він містить у підключеному потоці.

Обробник дає можливість взаємодії між потоками. Використовуючи обробник, фоновий потік може надсилати до нього результати, а обробник, який підключений до основного потоку, може оновлювати компоненти інтерфейсу на головній потоці.

AsyncTask

AsyncTask, що надається Android, використовує як потік, так і обробник, щоб полегшити виконання простих завдань у фоновому режимі та оновити результати від фонового потоку до основного потоку.

Приклади див. Для ниток Android, обробника, асинтактаску та пулів потоків для прикладів.


-1

Handler- це середовище зв'язку між потоками. В android він в основному використовується для спілкування з головною темою, створюючи та надсилаючи повідомлення через обробник

AsyncTask- використовується для виконання довгих запущених програм у фоновому потоці. За допомогою n AsyncTaskви можете виконати операцію у фоновій нитці та отримати результат у головному потоці програми.

Thread- це легкий процес для досягнення одночасності та максимального використання процесора. В android ви можете використовувати нитку для виконання дій, які не торкаються інтерфейсу програми

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.