Как реализованы Looper, Handler и MessageQueue? (1/3)
В предыдущих постах мы описали что такое и для чего используются Looper, Handler, и MessageQueue. Иногда на собеседованиях просят написать свою имплементацию этих сущностей. Хоть эти классы и считаются низкоуровневым Android API, они по большей части реализованы обычными средствами Java.
По своей сути Looper, Handler и MessageQueue реализуют шаблон producer/consumer. Тред-продюсер отправляет сообщения через Handler в коллекцию-буфер, реализованную классом MessageQueue. Тред-потребитель блокирован с помощью класса Looper, который ожидает и принимает сообщения из MessageQueue и передает их на обработку хэндлеру.
Первый этап использования этих сущностей – инициализация лупера, которая выполняется методом Looper.prepare(). Этот метод создает объект-looper вызовом приватного конструктора. При вызове конструктора также создается объект MessageQueue, который хранится в приватном поле класса Looper.
После этого метод prepare() сохраняет созданный объект в статическое поле типа ThreadLocal, имеющее package видимость.
Реализация инициализации лупера довольна простая, но она позволяет в любом месте программы и из любого треда получить лупер и очередь сообщений, связанные с текущим тредом.
Статический метод Looper.myLooper() просто достает лупер из переменной ThreadLocal:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Метод Looper.myQueue() получает лупер методом myLooper() и возвращает поле queue:
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
В следующем посте разберемся, как реализовано добавление сообщений в очередь.
#OS
В предыдущих постах мы описали что такое и для чего используются Looper, Handler, и MessageQueue. Иногда на собеседованиях просят написать свою имплементацию этих сущностей. Хоть эти классы и считаются низкоуровневым Android API, они по большей части реализованы обычными средствами Java.
По своей сути Looper, Handler и MessageQueue реализуют шаблон producer/consumer. Тред-продюсер отправляет сообщения через Handler в коллекцию-буфер, реализованную классом MessageQueue. Тред-потребитель блокирован с помощью класса Looper, который ожидает и принимает сообщения из MessageQueue и передает их на обработку хэндлеру.
Первый этап использования этих сущностей – инициализация лупера, которая выполняется методом Looper.prepare(). Этот метод создает объект-looper вызовом приватного конструктора. При вызове конструктора также создается объект MessageQueue, который хранится в приватном поле класса Looper.
После этого метод prepare() сохраняет созданный объект в статическое поле типа ThreadLocal, имеющее package видимость.
Реализация инициализации лупера довольна простая, но она позволяет в любом месте программы и из любого треда получить лупер и очередь сообщений, связанные с текущим тредом.
Статический метод Looper.myLooper() просто достает лупер из переменной ThreadLocal:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Метод Looper.myQueue() получает лупер методом myLooper() и возвращает поле queue:
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
В следующем посте разберемся, как реализовано добавление сообщений в очередь.
#OS