Короткий ответ: все они работают в одном потоке. При создании экземпляра из обратного вызова жизненного цикла 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
был выполнен. (Он также может проверить, правильное ли время, если вы отправили сообщение с задержкой.)
Просто для ясности: единственный способ заставить циклический поток делать что-то — отправить сообщение в его цикл. Это действует до тех пор, пока вы не вызовете quit() в циклере.
Относительно потока пользовательского интерфейса Android: в какой-то момент (вероятно, до того, как будут созданы какие-либо действия и т.п.) фреймворк настроил Looper
(содержащий MessageQueue
) и запустил его. С этого момента все, что происходит в потоке пользовательского интерфейса, проходит через этот цикл. Это включает в себя управление жизненным циклом деятельности и так далее. Все обратные вызовы, которые вы переопределяете (onCreate()
, onDestroy()
...), по крайней мере косвенно отправляются из этого цикла. Вы можете увидеть это, например, в трассировке стека исключения. (Можете попробовать, просто напишите int a = 1 / 0;
где-нибудь в onCreate()
...)
Я надеюсь в этом есть смысл. Извините за неясность ранее.
person
user634618
schedule
04.03.2011