Как в Android связаны потоки и луперы, может ли быть поток без лупера и сколько луперов на потоки
Что проверяют
Понимаете ли вы, на чём держится главный поток Android и откуда берутся Handler, MessageQueue и ANR. Следом спрашивают, почему бесконечный Looper.loop() не вешает приложение и как сделать фоновый поток с очередью сообщений.
Как отвечать
Отношение простое: у потока ноль или один Looper, у Looper ровно одна MessageQueue, а Handler к одному Looper можно привязать сколько угодно.
- связь:
Looper.prepare()создаёт лупер и кладёт его вThreadLocal, поэтомуLooper.myLooper()в каждом потоке возвращает свой.Looper.loop()крутит цикл: достать сообщение, отдать его целевомуHandler, взять следующее; - поток без лупера: обычное состояние. Простой
Thread, пул изExecutorsили потокDispatchers.IOлупера не имеют,Looper.myLooper()там вернётnull; - сколько луперов: второй вызов
Looper.prepare()в том же потоке бросаетRuntimeException«Only one Looper may be created per thread»; - главный поток: его лупер готовит
ActivityThread.main()черезLooper.prepareMainLooper(). Отрисовка, ввод и колбэки жизненного цикла идут сообщениями через эту очередь; - фоновый поток с очередью:
HandlerThread, лупер в нём уже подготовлен. Останавливается черезquitSafely(), иначе поток живёт вечно.
Почему loop() не грузит процессор: MessageQueue.next() при пустой очереди засыпает в нативном epoll, пока не придёт сообщение или не наступит время отложенного. ANR вызывает не сам цикл, а долгая обработка одного сообщения, например ввод, не обработанный за 5 секунд.
Где спотыкаются
Говорят, что без лупера поток не может работать. Может, лупер нужен только чтобы принимать сообщения через Handler.
Создают Handler() без аргументов в фоновом потоке и получают исключение Can't create handler inside thread ... that has not called Looper.prepare(). Этот конструктор устарел с API 30, лупер передают явно: Handler(Looper.getMainLooper()).
Приводят в пример AsyncTask. Он тоже устарел с API 30, лучше говорить о корутинах, где Dispatchers.Main работает поверх главного лупера.