Краткий ответ: они все работают в одном потоке.При создании экземпляра из обратного вызова жизненного цикла Activity
все они выполняются в основном потоке пользовательского интерфейса.
Длинный ответ:
Поток может иметь Looper
, который содержит MessageQueue
. Чтобы использовать эту возможность, вам нужно будет создать Looper
в текущем потоке, вызвав (статический) Looper.prepare()
, а затем запустить цикл, вызвав (также статический) Looper.loop()
.Они являются статическими, поскольку предполагается, что в каждом потоке должен быть только один Looper
.
Вызов loop()
обычно некоторое время не возвращает , но продолжает принимать сообщения ("задачи""," команды "или как вы хотите их вызывать) из MessageQueue
и обрабатывает их индивидуально (например, путем обратного вызова Runnable
, содержащегося в сообщении).Когда в очереди не осталось сообщений, поток блокируется до появления новых сообщений.Чтобы остановить Looper
, вы должны вызвать quit()
для него (что, вероятно, не останавливает цикл немедленно, а скорее устанавливает частный флаг, который периодически проверяется из цикла, сигнализируя о его остановке).
Однако вы не можете добавлять сообщения в очередь напрямую.Вместо этого вы регистрируете MessageQueue.IdleHandler
для ожидания обратного вызова queueIdle()
, в котором вы можете решить, хотите ли вы что-то или нет.Все обработчики вызываются по очереди.(Таким образом, «очередь» на самом деле не является очередью, а представляет собой коллекцию обратных вызовов, которые будут вызываться регулярно .)
Примечание относительно предыдущегопараграф: Это я на самом деле догадался.Я не смог найти никакой документации по этому вопросу, но это имело бы смысл.
обновление: см. ahcox 'комментарий и его ответ .
Поскольку это большая работа, фреймворк предоставляет класс Handler
для упрощения вещей .Когда вы создаете экземпляр Handler
, он (по умолчанию) привязывается к Looper
, уже прикрепленному к текущему потоку.(Handler
знает, к чему Looper
присоединиться, потому что мы вызывали prepare()
ранее, который, вероятно, сохранил ссылку на Looper
в ThreadLocal
.)
с Handler
, вы можете просто позвонить post()
, чтобы "поместить сообщение в очередь сообщений потока" (так сказать).Handler
позаботится обо всех функциях обратного вызова IdleHandler
и убедится, что ваш отправленный Runnable
выполнен.(Он также может проверить, подходит ли уже время, если вы отправили сообщение с задержкой.)
Просто чтобы прояснить: единственный способ действительно сделать зацикливание потока do что-то, чтобы отправить сообщение в его цикл.Это действует до тех пор, пока вы не вызовете quit () для петлителя.
Относительно потока пользовательского интерфейса Android: В какой-то момент (вероятно, до создания каких-либо действий и т.п.) фреймворк установил Looper
(содержащий MessageQueue
) и запустил его.С этого момента все, что происходит в потоке пользовательского интерфейса, проходит через этот цикл.Это включает в себя управление жизненным циклом деятельности и так далее.Все обратные вызовы, которые вы переопределяете (onCreate()
, onDestroy()
...), по крайней мере косвенно отправляются из этого цикла.Вы можете видеть это, например, в трассировке стека исключения.(Вы можете попробовать, просто напишите int a = 1 / 0;
где-нибудь в onCreate()
...)
Надеюсь, это имеет смысл.Извините за неясность ранее.