Какова цель Лупера и как его использовать?

Я новичок в Android. Я хочу знать, что делает класс Looper, а также как его использовать. Я прочитал Android документацию класса Looper, но я не могу это полностью понять. Я видел это во многих местах, но не мог понять его цели. Может ли кто-нибудь помочь мне, определив цель Looper, а также, если возможно, простой пример?

Ответ 1

Что такое Looper?

Looper - это класс, который используется для выполнения сообщений (Runnables) в очереди. Обычные нити не имеют такой очереди, например. простой поток не имеет очереди. Он выполняется один раз и после завершения выполнения метода, поток не запускает другое сообщение (Runnable).

Где мы можем использовать класс Looper?

Если кто-то хочет выполнить несколько сообщений (Runnables), тогда он должен использовать класс Looper, который отвечает за создание очереди в потоке. Например, при написании приложения, которое загружает файлы из Интернета, мы можем использовать класс Looper для загрузки файлов в очередь.

Как это работает?

Существует метод prepare() для подготовки Looper. Затем вы можете использовать метод loop() для создания цикла сообщений в текущем потоке, и теперь ваш Looper готов выполнить запросы в очереди до тех пор, пока вы не выйдете из цикла.

Вот код, по которому вы можете подготовить Looper.

class LooperThread extends Thread {
      public Handler mHandler;

      @Override
      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }

Ответ 2

Вы можете лучше понять, что такое Looper в контексте инфраструктуры GUI. Looper сделан, чтобы сделать 2 вещи.

1) Looper преобразует обычный поток, который завершается при возврате его метода run(), во что-то, работающее непрерывно до тех пор, пока не будет запущено приложение Android, что необходимо в графическом интерфейсе (Технически, он все еще завершается, когда возвращается метод run(). Но позвольте мне уточнить, что я имею в виду ниже).

2) Looper предоставляет очередь, в которой выполняются задания, которые также необходимы в среде GUI.

Как вы, возможно, знаете, когда приложение запускается, система создает поток выполнения для приложения, называемый "основным", и приложения Android обычно запускаются полностью в одном потоке по умолчанию "основной поток". Но главная нить не какая-то секретная, особая нить. Это просто обычный поток, похожий на потоки, которые вы создаете с помощью new Thread() кода new Thread(), что означает, что он завершается, когда возвращается его метод run()! Подумайте о приведенном ниже примере.

public class HelloRunnable implements Runnable {
    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }
}

Теперь давайте применим этот простой принцип к приложениям для Android. Что произойдет, если приложение Android будет работать в обычном потоке? Поток с именем "main" или "UI" или чем-то еще, запускает ваше приложение и рисует весь UI. Итак, первый экран отображается для пользователей. И что теперь? Основной поток заканчивается? Нет, не должно. Следует подождать, пока пользователи что-то сделают, верно? Но как мы можем достичь этого поведения? Ну, мы можем попробовать с Object.wait() или Thread.sleep(). Например, основной поток завершает свою начальную работу для отображения первого экрана и спит. Он пробуждается, что означает прерванный, когда выбирается новая работа. Пока все хорошо, но в данный момент нам нужна структура данных в виде очереди для хранения нескольких заданий. Подумайте о случае, когда пользователь касается экрана последовательно, и выполнение задачи занимает больше времени. Таким образом, нам нужна структура данных для хранения заданий, выполняемых в порядке "первым пришел - первым вышел". Кроме того, вы можете себе представить, что реализовать поток, который постоянно выполняется и обрабатывает задание, когда поступает, используя прерывание, нелегко и приводит к сложному и часто не поддерживаемому коду. Мы бы предпочли создать новый механизм для этой цели, и это то, что Лупер это все. Официальный документ класса Looper гласит: "С потоками по умолчанию не связан цикл сообщений", а Looper - это класс, "используемый для запуска цикла сообщений для потока". Теперь вы можете понять, что это значит.

Чтобы сделать вещи более понятными, давайте проверим код, в котором преобразован основной поток. Все это происходит в классе ActivityThread. В его методе main() вы можете найти приведенный ниже код, который превращает обычный основной поток в то, что нам нужно.

public final class ActivityThread {
    ...
    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        Looper.loop();
        ...
    }
}

и Looper.loop() зацикливается бесконечно и удаляет сообщение из очереди и обрабатывает по одному:

public static void loop() {
    ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        ...
        msg.target.dispatchMessage(msg);
        ...
    }
}

Итак, в основном, Looper - это класс, созданный для решения проблемы, возникающей в среде GUI. Но такого рода потребности могут возникать и в других ситуациях. На самом деле это довольно известный шаблон для многопоточного приложения, и вы можете узнать о нем больше в "Параллельном программировании на Java" Дуга Ли (особенно было бы полезно, глава 4.1.4 "Рабочие потоки"). Кроме того, вы можете себе представить, что этот вид механизма не уникален в платформе Android, но все графические интерфейсы могут нуждаться в некоторой аналогии с этим. Вы можете найти почти такой же механизм в среде Java Swing.

Ответ 3

Looper позволяет выполнять задачи последовательно в одном потоке. И обработчик определяет те задачи, которые нам нужно выполнить. Это типичный сценарий, который я пытаюсь проиллюстрировать в этом примере:

class SampleLooper extends Thread {
@Override
public void run() {
  try {
    // preparing a looper on current thread     
    // the current thread is being detected implicitly
    Looper.prepare();

    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();

    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  } 
}
}

Теперь мы можем использовать обработчик в некоторых других потоках (например, поток ui), чтобы выполнить задачу на Looper для выполнения.

handler.post(new Runnable()
{
public void run() {
//This will be executed on thread using Looper.
    }
});

В потоке пользовательского интерфейса мы имеем неявный Looper, который позволяет обрабатывать сообщения в потоке ui.

Ответ 4

Android Looper обертка прикрепить MessageQueue к Thread и управляет обработкой очереди. Это выглядит очень загадочно в документации Android, и часто мы можем столкнуться с проблемами доступа к пользовательскому интерфейсу Looper. Если мы не понимаем основ, с этим становится очень трудно справиться.

Вот статья, которая объясняет жизненный цикл Looper, как его использовать и как использовать Looper в Handler

enter image description here

Looper = Thread + MessageQueue

Ответ 5

Определение Looper & Handler:

Looper - это класс, который превращает поток в поток конвейера, а обработчик предоставляет вам механизм для вставки задач в него из любых других потоков.

Подробности:

Таким образом, поток PipeLine - это поток, который может принимать больше задач из других потоков через обработчик.

Looper назван так, потому что он реализует цикл - берет следующую задачу, выполняет ее, затем берет следующую и так далее. Обработчик называется обработчиком, потому что он используется для обработки или принятия следующей задачи каждый раз из любого другого потока и передачи в Looper (Thread или PipeLine Thread).

Пример:

Отличным примером Looper and Handler или PipeLine Thread является загрузка нескольких изображений или загрузка их на сервер (Http) по одному в одном потоке вместо запуска нового потока для каждого сетевого вызова в фоновом режиме.

Узнайте больше здесь о Looper и Handler и определении Threading Thread:

Android Guts: Введение в Loopers и Обработчики

Ответ 6

A Looper имеет synchronized MessageQueue, который использовался для обработки сообщений, помещенных в очередь.

Он реализует специальный шаблон хранения Thread.

Только один Looper за Thread. Ключевыми методами являются prepare(), loop() и quit().

prepare() инициализирует текущий Thread как Looper. prepare() - это метод static, который использует класс ThreadLocal, как показано ниже.

   public static void prepare(){
       ...
       sThreadLocal.set
       (new Looper());
   }
  • prepare() должен быть вызван явно перед запуском цикла событий.
  • loop() запускает цикл событий, который ожидает, что сообщения поступят в конкретный поток сообщений Thread. После получения следующего сообщения метод loop() отправляет сообщение его целевому обработчику
  • quit() отключает цикл событий. Он не завершает цикл, но вместо этого он вставляет специальное сообщение

Looper можно запрограммировать в Thread с помощью нескольких шагов

  • Расширить Thread

  • Вызвать Looper.prepare() для инициализации Thread как a Looper

  • Создайте один или несколько Handler (s) для обработки входящих сообщений

  • Вызов Looper.loop() для обработки сообщений до тех пор, пока цикл не будет передан quit().

Ответ 7

Продолжительность жизни java Thread завершена после завершения метода run(). Одну нить нельзя запустить снова.

Looper преобразует нормальный Thread в цикл сообщения. Ключевыми методами Looper являются:

void prepare ()

Инициализировать текущий поток в качестве петлителя. Это дает вам возможность создавать обработчики, которые затем ссылаются на этот петлитель, прежде чем начать цикл. Обязательно вызовите loop() после вызова этого метода и завершите его, вызвав quit().

void loop ()

Запустите очередь сообщений в этом потоке. Обязательно вызовите quit(), чтобы закончить цикл.

void quit()

Выход из петлителя.

Заставляет метод loop() завершаться без обработки каких-либо сообщений в очереди сообщений.

Эта статья статьи о мыслях от Janishar объясняет основные понятия красивым способом.

введите описание изображения здесь

Looper связан с потоком. Если вам нужно Looper в потоке пользовательского интерфейса, Looper.getMainLooper() вернет связанный поток.

Вам нужно Looper связать с Handler.

Looper, Handler, а HandlerThread - метод андроидов для решения задач асинхронного программирования.

Как только у вас есть Handler, вы можете вызвать API ниже.

post (Runnable r)

Заставляет Runnable r добавляться в очередь сообщений. Runnable будет запущен в потоке, к которому прикреплен этот обработчик.

boolean sendMessage (Message msg)

Отбрасывает сообщение в конец очереди сообщений после всех ожидающих сообщений до текущего времени. Он будет получен в handleMessage (Message) в потоке, прикрепленном к этому обработчику.

HandlerThread - это удобный класс для запуска нового потока с петлевым механизмом. Затем петлитель можно использовать для создания классов обработчиков

В некоторых сценариях вы не можете запускать задачи Runnable в потоке пользовательского интерфейса. например Сетевые операции: отправить сообщение в сокет, открыть URL-адрес и получить контент, прочитав InputStream

В этих случаях полезно использовать HandlerThread. Вы можете получить объект Looper из HandlerThread и создать Handler на HandlerThread вместо основного потока.

HandlerThread будет выглядеть следующим образом:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

См. ниже сообщение, например, код:

Android: тост в потоке

Ответ 8

Этот ответ не имеет никакого отношения к вопросу, но использование петлителя и способ создания человеком обработчика и петлителя во ВСЕХ ответах здесь - это плохая практика (некоторые объяснения верны, хотя), я должен опубликовать это:

HandlerThread thread = new HandlerThread(threadName);
thread.start();
Looper looper = thread.getLooper();
Handler myHandler = new Handler(looper);

и для полная реализация

Ответ 9

Обработка нескольких элементов вниз или загрузки в Service является лучшим примером.

Handler и AsnycTask часто используются для распространения событий/сообщений между пользовательским интерфейсом (thread) и рабочим потоком или с задержкой действий. Поэтому они больше связаны с пользовательским интерфейсом.

A Looper обрабатывает задачи (Runnables, Futures) в связанной с потоком очереди в фоновом режиме - даже без взаимодействия пользователя или с отображаемым интерфейсом (приложение загружает файл в фоновом режиме во время разговора).

Ответ 10

Что такое Лупер?

ОТ ДОКУМЕНТОВ

Looper

Looper Class используется для запуска цикла сообщений для thread. По умолчанию потоки не имеют циклы сообщений, связанной с ними; чтобы создать его, вызовите prepare() в потоке, который должен запустить цикл, а затем loop() чтобы он обрабатывал сообщения до тех пор, пока цикл не будет остановлен.

  • Looper - это цикл обработки сообщений:
  • Важным символом Looper является то, что он связан с потоком, в котором создается Looper
  • Класс Looper поддерживает MessageQueue, который содержит список сообщений. Важным символом Looper является то, что он связан с потоком, в котором создается Looper.
  • Looper назван так, потому что он реализует цикл - берет следующую задачу, выполняет ее, затем берет следующую и так далее. Handler называется обработчиком, потому что кто-то не может придумать лучшего имени
  • Android Looper - это класс Java в пользовательском интерфейсе Android, который вместе с классом Handler обрабатывает события пользовательского интерфейса, такие как нажатия кнопок, перерисовка экрана и переключение ориентации.

Как это устроено?

enter image description here

Создание Looper

MessageQueue получает Looper и MessageQueue, вызывая Looper.prepare() после своего запуска. Looper.prepare() идентифицирует вызывающий поток, создает объект Looper и MessageQueue и связывает поток

ОБРАЗЕЦ КОДА

class MyLooperThread extends Thread {

      public Handler mHandler; 

      public void run() { 

          // preparing a looper on current thread  
          Looper.prepare();

          mHandler = new Handler() { 
              public void handleMessage(Message msg) { 
                 // process incoming messages here
                 // this will run in non-ui/background thread
              } 
          }; 

          Looper.loop();
      } 
  }

Для получения дополнительной информации проверьте ниже пост