Android. Собеседование #7. Многопоточность. Handler. Looper.

Автор:

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 поток.

 

Ваш адрес email не будет опубликован. Обязательные поля помечены *