Какова цель Looper и как ее использовать?

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

9 ответов


что такое Looper?

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

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

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

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

здесь prepare() метод подготовки петлителя. Тогда вы можете использовать loop() метод для создания цикла сообщений в текущем потоке, и теперь ваш 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();
      }
  }

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

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

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

как вы знаете, при запуске приложения система создает поток выполнения для приложения, называемого "main", а приложения Android обычно запускаются полностью в одном потоке по умолчанию"main thread". Но!--10-->основной поток не какой-то секрет, специальный поток. Это просто обычный поток, подобный потокам, которые вы создаете с помощью 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 app. Что произойдет, если приложение для Android работает в обычном потоке? Поток под названием "main "или" UI " или что-то еще запускает ваше приложение и рисует весь пользовательский интерфейс. Таким образом, первый экран отображается для пользователей. И что теперь? Основной поток заканчивается? Нет, не должно. Это должно подождать, пока пользователи что-то не сделают, верно? Но как мы можем добиться такого поведения? Что ж, мы можем попробовать. с Object.wait() или Thread.sleep(). Например, основной поток завершает начальную работу для отображения первого экрана и спит. Он просыпается, что означает прерывание, когда новая работа выполняется. Пока все хорошо, но на данный момент нам нужна структура данных в виде очереди для выполнения нескольких заданий. Подумайте о случае, когда пользователь касается экрана последовательно, и задача занимает больше времени, чтобы закончить. Итак, нам нужна структура данных для выполнения заданий, выполняемых в порядке "первый-в-первый-выход". Кроме того, вы можете себе представить, реализация постоянно работающего потока с использованием прерывания не проста и приводит к сложному и часто недостижимому коду. Мы предпочли бы создать новый механизм для этой цели, и вот что такое Looper. The официальный документ класса Looper говорит: "потоки по умолчанию не имеют связанного с ними цикла сообщений", а Looper-это класс"используемый для запуска цикла сообщений для потока". Теперь вы можете понять, что это средства.

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

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

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

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, но все рамки GUI могут нуждаться в чем-то подобном этому. Вы можете найти почти такой же механизм в Java Swing рамки.


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

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 thread) для публикации задачи на Looper для выполнения.

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

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


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

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

enter image description here

петлителя = Поток + MessageQueue


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

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

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

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

Подробнее читайте здесь о Петлителе и обработчике и определении потока конвейера:

Android кишки: введение в Петлители и Обработчики


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

он реализует Thread Специфическая Картина Хранения.

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

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

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

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

  1. расширения Thread

  2. вызов Looper.prepare() для инициализации потока как Looper

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

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

продолжительность жизни java нить после окончания run() метод. Же поток не может быть запущен снова.

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

void prepare ()

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

void loop ()

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

void quit()

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

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

этой статьи mindorks Джанишар объясняет основные концепции в Ницце путь.

enter image description here

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

вам нужно Looper связано с проводник.

Looper, Handler и HandlerThread являются способом Android для решения проблем асинхронного программирования.

после Handler, вы можете позвонить ниже Апис.

post (Runnable r)

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

boolean sendMessage (Message msg)

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

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

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

в этих случаях HandlerThread полезно. Вы можете получить Looper объект HandlerThread и создать Handler on 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: тост в потоке


этот ответ не имеет ничего общего с вопросом, но использование looper и то, как люди создали обработчик и looper во всех ответах здесь, - это просто плохая практика (некоторые объяснения правильны), я должен опубликовать это:

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

и полной реализации


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

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

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