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


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

9 399

9 ответов:

что такое Looper?

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

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

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

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

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

вот код, с помощью которого вы можете подготовить петлителя.

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. Петлитель сделан, чтобы сделать 2 вещи.

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

2) Looper предоставляет очередь где есть работа предстоит сделать, - это очередь, которая также необходима в рамках графического интерфейса.

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

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

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 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

Looper = Thread + MessageQueue

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

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

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

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

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

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

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

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

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

prepare() инициализирует текущий Thread как Looper. prepare() и 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 Thread после окончания 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 R для добавления в очередь сообщений. Runnable будет выполняться в потоке, к которому присоединен этот обработчик.

boolean sendMessage (Message msg)

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

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

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

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

The 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 (поток) и рабочий поток или отложить действия. Таким образом, они больше связаны с пользовательским интерфейсом.

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