Android Looper и стек вызовов

Мне было интересно, как класс Looper обрабатывает Runnables (через класс Handler) в потоке, к которому привязан Looper? Если петлитель выполняет цикл через свой messageQueue, то, конечно, это будет операция блокировки для этого потока? Я предполагаю, что это само по себе должно выполняться с помощью тонкой обрезки, но тогда как он добавляет опубликованный метод Runnables run () в стек потоков хостов?

Много вопросов! Любая помощь приветствуется. Благодаря!

РЕДАКТИРОВАТЬ:

Просматривая класс класса класса Looper, я вижу ниже, что меня еще больше смущает, поскольку все комментарии относятся к петлевому механизму, запущенному в основном потоке, а также к его блокирующей операции при ожидании новых сообщений в MessageQueue. Как это не блокирует пользовательский интерфейс / основной поток?

/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static final void loop() { Looper me = myLooper(); 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(); while (true) { Message msg = queue.next(); // might block //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.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("Looper", "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.recycle(); } } } /** * Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static final Looper getMainLooper() { return mMainLooper; } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static final Looper myLooper() { return (Looper)sThreadLocal.get(); } // sThreadLocal.get() will return null unless you've called prepare(). private static final ThreadLocal sThreadLocal = new ThreadLocal(); /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } 

Вы абсолютно правы. Возникающий поток, который вызывает Looper.start (), вызывается в потоке, в который обрабатываются все опубликованные Runnables и Messages. Это действительно означает, что этот поток заблокирован.

Хорошо, оглядевшись вокруг стека, я нашел еще один вопрос, который отвечает мне. Моя основная путаница исходила из того, что я не понял этого положения . Я неправильно думал обо всем, кроме материала, отправленного в Handlers (и добавленного в Loopers MessageQueue), выполнялся в линейном стеке вызовов, но, думая об этом, более вероятно, что любая программа с пользовательским интерфейсом реализована и делает Гораздо больше смысла, что каждая вещь в потоке пользовательского интерфейса возникла из Looper, и все пути исключения в этой теме вернутся к ней! Спасибо Berdon за попытку ответить на мой вопрос, я уверен, что не очень хорошо объяснил свою проблему 🙂

Что касается потока пользовательского интерфейса Android: в какой-то момент (вероятно, до того, как будут созданы какие-либо действия и т. Д.), Среда настроила Looper (содержащую MessageQueue) и запустила его. С этого момента все, что происходит в потоке пользовательского интерфейса, проходит через этот цикл . Это включает в себя управление жизненным циклом деятельности и т. Д. Все обратные вызовы, которые вы переопределяете (onCreate (), onDestroy () …), по крайней мере, опосредованно отправляются из этого цикла. Вы можете увидеть это, например, в трассировке стека исключения. (Вы можете попробовать, просто напишите int a = 1/0, где-то в onCreate () …)