Что произойдет, если обработчик отправит сообщение в поток после Looper.prepare (), но до вызова Looper.loop ()?

Рассмотрим следующий фрагмент:

Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); getLooper().quitSafely(); } }; for(int i = 0; i < urls.size(); i++) { useCaseProvider.get().execute(callback, handler, urls.get(i), threadPool); } Looper.loop(); //Continue processing the results of all the use cases after the //loop has been asked to terminated via the handler 

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

Вопрос: Если один из этих вариантов использования каким-то образом выполнялся достаточно быстро и сделал обратный вызов, прежде чем я смог нажать Looper.loop (); Было ли сообщение поставлено в очередь или просто потеряно? Обратные вызовы отправляются обратно в этот поток обработчиком, проводящим runnable в исходный поток.

Solutions Collecting From Web of "Что произойдет, если обработчик отправит сообщение в поток после Looper.prepare (), но до вызова Looper.loop ()?"

Предполагая, что вы вызвали Looper.prepare () до вашего использованияCaseProvider, доставляя результаты, вы должны быть в порядке. Если Looper.prepare не был вызван, вы должны видеть, что RuntimeException выбрасывается.

Объект Looper привязан к локальному потоку, в котором размещается очередь сообщений. Функция Looper.prepare построит эту очередь сообщений, после чего вы сможете начать массовое рассылку сообщений. Как только вы запустите Looper.loop (), тогда начнутся выполнение ожидающих сообщений.

Глядя на фрагмент, я не слишком уверен, как все связано. Как правило, вы хотите построить петлитель следующим образом:

 private static final class MyThread extends Thread { private Handler mHandler; @Override public void run() { Looper.prepare(); mHandler = new Handler() { @Override public void handleMessage(Message msg) { // handle message } }; Looper.loop(); } public Handler getHandler() { return mHandler; } } 

Я предполагаю, что ваш пул потоков – это пул потоков MyThread, каждый из которых имеет свой собственный Looper. Пул потоков должен инициализировать ваши потоки, поэтому, как только вы доставляете Runnable для выполнения вашим потоком, метод run () должен инициализировать Looper.

С другой стороны, если вы хотите связать своего обработчика с определенным петлером (т. Е. Вы не создаете обработчик в потоке, как описано выше), вы должны передать поток Looper в конструктор, например:

 Handler h = new Handler(myLooperThread); 

Если вы не укажете это, тогда обработчик использует поток, в котором он был создан, чтобы захватить Looper этого потока из объекта ThreadLocal.

Наконец, если ваши намерения состоят в том, чтобы сообщения, доставленные на обработчике, связанные с потоком пользовательского интерфейса, вам не следует беспокоиться о вызове Looper.prepare или Looper.loop. Это обрабатывается Activity.