Сегодня я прочитал несколько блогов и исходный код о том, как Handler & Looper работают вместе.Почему основной поток Looper.loop() не блокирует поток пользовательского интерфейса?
Основываясь на том, что я узнал, мы можем иметь только один Looper на каждом потоке, используя магию ThreadLocal
. Обычно обработчик инициируется в основном потоке, иначе вы должны вручную запустить или сказать: prepare
Looper в отдельном потоке, а затем зацикливать его.
Что меня совсем смущает loop()
в главной теме. Когда я прочитал это в исходном коде Looper. Это бесконечный цикл для обработки очереди сообщений, а затем отправка сообщений для обработки обратных вызовов.
В соответствии с этим https://stackoverflow.com/a/5193981/2290191, обработчик и его Looper запускаются в той же теме.
Если на основном потоке есть бесконечный цикл, не блокирует ли он весь пользовательский интерфейс?
Я знаю, что я должен быть настолько глупым, чтобы что-то пропустить. Но было бы прекрасно, если бы кто-то раскрыл секрет этого.
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
Не думаю, что вы внимательно прочитали мой вопрос. Я имею в виду, если существует 'for (;;) {}' loop on main thread, как можно отправлять сообщения для рисования пользовательского интерфейса? –
Я сделал, я не думаю, что вы поняли мой ответ. Одно из сообщений петлителя вызывает ничью. Рисование - это специальное сообщение, отправленное на этот петлитель. –
Или по-другому: что вы думаете о том, что основным потоком является то, что Looper обрабатывает сообщения и вызывает ваш код в ответ на него. Это метод, называемый циклом событий или циклом сообщений, который является общим в программировании, управляемом событиями.Вот подробное объяснение Android http://mattias.niklewski.com/2012/09/android_event_loop.html –