Android: Коли я повинен використовувати обробник () і коли потрібно використовувати нитку?


129

Коли мені потрібно щось запустити асинхронно , наприклад, тривале завдання або логіка, що використовує мережу, або з будь-якої причини, запуск нової теми та її запуск справно працює. Створення обробника та його запуск також працює. Яка різниця? Коли я повинен використовувати кожен? Які переваги / причини використовувати a, Handlerа не a Thread?

PS. - Заради цього питання ігноруємо AsyncTask. - Handler().postDelayedвикористання випадків мені зрозуміле, для цього питання припустимо, що мені потрібно негайно почати завдання.


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

1
@ kabuto178 добре, є й інші переваги обробників, які варто згадати, що ви пропустили.
Наприклад

Відповіді:


168

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

Цікаво, що при використанні потоку часто корисно також використовувати обробник як засіб зв’язку між робочою ниткою, яку ви починаєте, та основною ниткою.

Типова взаємодія між різьбленням та обробкою може виглядати приблизно так:

Handler h = new Handler(){
    @Override
    public void handleMessage(Message msg){
        if(msg.what == 0){
            updateUI();
        }else{
            showErrorDialog();
        }
    }
};

Thread t = new Thread() {
    @Override
    public void run(){
        doSomeWork();
        if(succeed){
            //we can't update the UI from here so we'll signal our handler and it will do it for us.
            h.sendEmptyMessage(0);
        }else{
            h.sendEmptyMessage(1);
        }
    }   
};

Взагалі, приходіть додому, що ви повинні використовувати Thread будь-який час, коли ви робите якусь роботу, яка може бути тривалою або дуже інтенсивною (наприклад, будь-яка мережа, IO файлів, важкі арифметичні тощо).


Дякуємо за швидку відповідь та кількість вкладеного часу (та швидкість вашої відповіді !!)! Отже, дозвольте мені зрозуміти, чи отримав я це: Обробник розроблений для полегшення незаблокування зв'язку між робочими потоками та потоком інтерфейсу користувача?
JRun

3
@JRun Це одне із застосувань - так. Ознайомтеся з описом Handler в документах Java, щоб отримати додаткову інформацію про нього. Включаючи інше його використання (для планування повідомлень та бігунів, які будуть виконані як певний момент у майбутньому).
FoamyGuy

чудово пояснив @FoamyGuy!
tony9099

Привіт, чи гарантовано це updateUI()після запуску onCreateView(після завантаження нових переглядів)?
Zyoo

1
Чому саме так message.what()? Чи не було б просто if(msg == 0){? Дуже дякую! :)
Ruchir Baronia

64

Обробник і нитка - це справді дві різні речі.

Потрібно створити нитку для виконання тривалих завдань.

Обробник є дуже зручним об'єктом для зв'язку між двома потоками (наприклад: фоновий потік потребує оновлення інтерфейсу користувача. Ви можете використовувати обробник, щоб розмістити деякий Runnable з вашого фонового потоку до потоку інтерфейсу користувача).

Таким чином, у вас немає вибору між обробником або потоком. Використовуйте нитку для виконання важких робіт! (ви можете використовувати обробник, якщо ваш фоновий потік призведе до виконання певної роботи в іншій потоці - більшість часу потік інтерфейсу користувача)


Дякуємо за швидку відповідь та кількість вкладеного часу (та швидкість вашої відповіді !!)!
липня

28

Handlerі Threadце дві різні речі, але вони не суперечать одна одній. Ви можете мати a Handlerі a Threadодночасно, і фактично кожен Handlerповинен працювати в a Thread.

Щоб отримати детальнішу інформацію, ви можете ознайомитися з цією статтею .

введіть тут опис зображення


19

А Handlerпрацює на тому ж Thread, а Threadпрацює на іншому потоці.

Використовуйте обробник, якщо вам потрібно запустити щось на тій самій нитці , зазвичай це елемент GUI або щось подібне.

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


6
чому я повинен використовувати обробник, якщо я хочу запустити щось на одній темі? яка мета методу mHandler.post (...)?
Elias

1
Elias, у такому випадку ви можете використовувати обробник, якщо хочете, щоб певна задача виконувалася через певний проміжок часу, або повторювала завдання кожні X кількість часу. Якщо ви не хочете користуватися цими речами, ви маєте рацію. користуватися обробником недоцільно. ви можете просто робити речі GUI тут же, а потім, bcoz, ви все одно знаходитесь у потоці користувальницького інтерфейсу, тому що обробник працює на потоці, в якому він був створений.
tony9099

14

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

ВИКОРИСТАННЯ:

Нитка: виконувати завдання в саператній (фоновій) темі, ніж потік інтерфейсу. (допомагає розблокувати потік інтерфейсу)

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

Погляньте на цю статтю


4

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

Для цього можна використовувати клас android.os.Handler або клас AsyncTasks.

Клас Handler може оновити інтерфейс користувача. Обробник надає методи отримання примірників класу Повідомлення або Виконання.

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

... Докладніше тут про теми тощо (включає туроріали для різних механізмів введення та синхронізації та коли використовувати що)


Дякуємо, що знайшли час, щоб відповісти на моє запитання. Я люблю блог Ларса Фогеля, за ним дуже проникливий і простий. Дякую!
JRun

2

Які переваги / причини використовувати обробник, а не нитку?

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

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

Для обробника є два основних напрямки використання:

  1. Запланувати повідомлення та Runnables, які слід виконати як деякий момент у майбутньому
  2. Щоб епдіеее дію , яка виконуватиметься в іншому потоці , ніж свій власний.

Якщо ви використовуєте Java-нитки, вам доведеться самостійно обробляти щось - синхронізація з основною ниткою, скасування потоку тощо.

Цей єдиний потік не створює пул потоків, якщо ви не використовуєте ThreadPoolExecutorабо ExecutorServiceAPI.

(Взятий цей запит з ваших коментарів до відповіді Blackbelt)

Чому б не використовувати Виконавця? і навіть якщо я хотів використовувати для цього обробник, як?

Довідка: Стаття про виконання теми

Існують певні види роботи, які можна звести до високопаралельних, розподілених завдань. Завдяки чистому обсягу робочих пакетів це створює AsyncTaskі HandlerThreadне є відповідними класами. Однопоточний характер AsyncTaskперетворив би всю роботу з нитками в лінійну систему. HandlerThreadЗ іншого боку, використання класу вимагатиме від програміста вручну керувати балансуванням навантаження між групою потоків.

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

 BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
 ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

Ви можете ознайомитись з цією статтею керівництва для розробників у create-threadpool для отримання більш детальної інформації.

Перегляньте цю публікацію для використання Handlerдекількох екземплярів Runnable. У цьому випадку всі Runnableзавдання виконуватимуться в одній темі.

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


1

Handlerможе використовуватися разом із Threadтим, щоб створити механізм черги. Ви можете використовувати, handlerщоб написати щось наThread Looper


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

Виконавець трохи інший. Для того, щоб використовувати його, ви повинні розширити потік і під час виклику викликати static.metohd prep.of клас Looper. після виклику циклу статичного методу створюється черга, і ви можете використовувати замовлення handlerbin для пересилання запитів і отримання результатів назад
Blackbelt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.