1. Особенности работы потоков в Android приложении?
В приложении на Android создается главный, так называемый UI поток, который обрабатывает основные события в приложении, такие как взаимодействие с пользовательским интерфейсом (например, нажатие на кнопку), графические изменения, создание широковещательного сообщения и т.д. UI поток работает на протяжении всего жизненного цикла приложения.
При запуске нового потока, в случае необходимости изменить UI в нашем приложении, например цвет какого-либо TextView, необходимо использовать средства, которые имеют доступ к UI потоку, иначе произойдёт падение нашего приложения. Доступ к UI имеет только главный поток приложения.
Вся логика приложения, которая занимает продолжительное время, например обращение к базе данных, сложные вычисления, REST запросы и т.д. должны выполняться в отдельном потоке, иначе приложение зависнет и примерно через 5 секунд вызовет ANR (application not respoding) ошибку.
2. Что такое Looper и MessageQueue?
MessageQueue – класс, который хранит список из объектов Message, которые должны быть выполнены по принципу FIFO. и взаимодействует с Looper для обработки сообщений.
Looper – класс, предназначенный для обработки очереди MessageQueue, в которую Handler отправляет сообщения (объекты Message) о необходимости обработать изменения в приложении. После запуска приложения, в его основном потоке создаётся экземпляр Looper, главный UI Looper приложения, который при помощи метода loop() запускает бесконечный цикл и проверяет, появились ли новые сообщения в MessageQueue.
При создании нового потока, необходимо обязательно создать looper внутри него, при помощи последовательного вызова методов Looper.prepare() → Looper.loop(), иначе при попытке изменить данные в UI потоке приложения, произойдёт ошибка.
class StackOfSkillsThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // some logic here } }; Looper.loop(); } }
Для завершения работы Looper необходимо вызвать метод quitSafely() для того чтобы завершить работу Looper и быть уверенным в том, что все сообщения в MessageQueue были обработаны.
3. Что такое Handler и HandlerThread?
Handler это класс, который предназначен для управления потоками в приложении. Получает сообщения от Looper из MessageQueue и он же отправляет сообщения в MessageQueue. С его помощью мы можем связать UI поток нашего приложения с другими потоками.
При создании нового объекта Handler, по умолчанию он привязывается к этому потоку и MessageQueue в этом же потоке. Т.е. если мы создаём новый Thread и в нём создаём Handler, то он не будет иметь доступа к UI потоку приложения. Для взаимодействия с UI потоком, необходимо инициализировать looper в этом потоке, либо предоставить Main Looper для нашего Handler
Handler mHandler = new Handler(Looper.getMainLooper())
HandlerThread – класс, который наследуется от Thread. Уже включает в себя Looper, MessageQueue и готов для создания нового потока, с последующей передачей данных в UI поток.