Лучшее использование HandlerThread над другими подобными классами

Я пытаюсь понять лучший вариант использования HandlerThread .

Согласно определению:

«Удобный класс для запуска нового потока, в котором есть петлитель. Затем можно использовать петлитель для создания классов обработчиков. Обратите внимание, что start () еще нужно вызвать».

Возможно, я ошибаюсь, но аналогичную функциональность я могу достичь, используя Thread , Looper и Handler . Итак, когда я должен использовать HandlerThread ? Пример был бы очень полезен.

Solutions Collecting From Web of "Лучшее использование HandlerThread над другими подобными классами"

Вот пример реальной жизни, когда HandlerThread становится удобным. Когда вы регистрируетесь в onPreviewFrame() предварительного просмотра камеры, вы получаете их в onPreviewFrame() . Документация объясняет, что этот обратный вызов вызывается в событии, из которого был вызван поток open (int) .

Обычно это означает, что обратный вызов будет вызван в основном потоке (UI). Таким образом, задача обращения с огромными массивами пикселей может зависеть при открытии меню, анимации анимации или даже при статистике, напечатанной на экране.

Простое решение – создать new HandlerThread() и делегировать Camera.open() в этот поток (я сделал это через post(Runnable) , вам не нужно реализовывать Handler.Callback ).

Обратите внимание, что всякая работа с камерой может быть выполнена как обычно, вам не нужно делегировать Camera.startPreview() или Camera.setPreviewCallback() в HandlerThread. Чтобы быть в безопасности, я жду, пока фактический Camera.open(int) завершится, прежде чем продолжить основной поток (или какой-либо поток был использован для вызова Camera.open() перед изменением).


Итак, если вы начинаете с кода

 try { mCamera = Camera.open(1); } catch (RuntimeException e) { Log.e(LOG_TAG, "failed to open front camera"); } // some code that uses mCamera immediately 

Сначала извлеките его как частный метод:

 private void oldOpenCamera() { try { mCamera = Camera.open(1); } catch (RuntimeException e) { Log.e(LOG_TAG, "failed to open front camera"); } } 

И вместо вызова oldOpenCamera() просто используйте newOpencamera() :

 private void newOpenCamera() { if (mThread == null) { mThread = new CameraHandlerThread(); } synchronized (mThread) { mThread.openCamera(); } } private CameraHandlerThread mThread = null; private static class CameraHandlerThread extends HandlerThread { Handler mHandler = null; CameraHandlerThread() { super("CameraHandlerThread"); start(); mHandler = new Handler(getLooper()); } synchronized void notifyCameraOpened() { notify(); } void openCamera() { mHandler.post(new Runnable() { @Override public void run() { oldOpenCamera(); notifyCameraOpened(); } }); try { wait(); } catch (InterruptedException e) { Log.w(LOG_TAG, "wait was interrupted"); } } } 

Обратите внимание, что вся цепочка сообщений notify ()wait () не требуется, если вы не получаете доступ к mCamera в исходном коде сразу после ее открытия.

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

Вот ссылка на исходный код HandlerThread и Looper .

Если вы посмотрите на два, вы увидите, что HandlerThread – это именно то, что он говорит – удобный способ начать Thread , у которого есть Looper . Почему это существует? Поскольку потоки по умолчанию не имеют цикла сообщений . HandlerThread – это просто простой способ создать тот, который делает. Не могли бы вы дублировать эту функцию с помощью Handler , Thread и Looper – судя по исходному коду – ответ да.

Executor – другой. Executor принимает предоставленные выполняемые задачи и – догадывается, что их выполняет. Почему это необходимо? Это позволяет отделить выполнение задачи от ее фактического вещества . Когда вы это используете? Предположим, что у вас была ситуация, требующая одновременного выполнения нескольких задач. Вы можете выбрать, используя Executor , для запуска их всех в одном потоке, чтобы они выполнялись серийно. Или вы можете использовать фиксированный пул потоков, чтобы некоторые, но не все, запускались одновременно. В любом случае сущность задачи – то есть то, что она на самом деле делает, – отличается от того, как она выполняется.