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

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


person Khawar Raza    schedule 29.09.2011    source источник
comment
Я только что нашел чрезвычайно подробное и ясное объяснение Looper и его использования в Safari Books Online. К сожалению, я подозреваю, что доступ будет бесплатным только на ограниченное время. safaribooksonline.com/library/view/efficient-android- потоки /   -  person Joe Lapp    schedule 19.12.2015
comment
Статьи и справочные страницы Android требуют от вас понимания предыдущей статьи, прежде чем вы сможете понять текущую. Я предлагаю вам прочитать статьи Activity и Service в руководствах по Api, а затем прочитать Handler и Looper. Это также помогает, если вы понимаете, что такое поток (не поток Android, а поток в целом ... например, POSIX).   -  person FutureSci    schedule 20.02.2016
comment
Я нашел эту статью полезной: codetheory.in/   -  person Hermandroid    schedule 04.07.2017


Ответы (13)


Что такое 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();
      }
  }
person Dharmendra    schedule 29.09.2011
comment
Таким образом, петлитель можно использовать для обновления основного потока, скажем, ... процент загрузки (10%, 20%, 30% ... и т. Д.). По сути, обратная связь, которую вы могли бы передать в индикатор выполнения? - person HGPB; 30.05.2012
comment
AsyncTask лучше для этой цели и менее сложен, поскольку он инкапсулирует все управление потоками. - person Fernando Gallego; 29.11.2012
comment
Перед методами run () и handleMessage () должны быть аннотации @Override. - person Andrew Mackenzie; 18.04.2013
comment
Поскольку мы переопределяем этот метод, он должен @override над этими методами run и handleMessage. - person Dharmendra; 18.04.2013
comment
В документации указано, что вы должны вызвать looper.quit. В приведенном выше коде Looper.loop будет блокироваться на неопределенный срок. - person AndroidDev; 05.07.2013
comment
Я запутался, как заставить Looper.loop () не блокировать? Зачем вам вызывать Looper.Quit (), если вы хотите, чтобы цикл сообщений для потока запускался? - person Andi Jay; 18.07.2013
comment
Как выйти из петли. Я имею в виду, где включить Looper.quit () в приведенный выше пример кода? - person Seenu69; 17.10.2013
comment
Насколько я знаю, вы можете вызвать Looper.myLooper (). Quit (); к вполне текущей петле сучка. Вы можете вызвать этот метод, когда получили конкретное сообщение в методе handleMessage. - person Dharmendra; 25.10.2013
comment
Вызов quit не является обязательным в зависимости от варианта использования. - person RichieHH; 31.07.2014
comment
И я; вы должны выйти после обработки сообщений, чтобы затем можно было посвятить эту ветку, например, пост-мониторингу. Например, поток сидит там, ожидая прибытия асинхронных семян. Когда они прекратят мониторинг и поработают над тем же потоком. - person RichieHH; 31.07.2014
comment
Я думаю, было бы лучше использовать удобный класс HandlerThread. для нити с петлителем. - person Nimrod Dayan; 08.09.2014
comment
Чтобы выйти из цикла, просто вызовите метод выхода из вызываемого потока в onDestroy (). mWorkerThread.quit () проверит, есть ли у него цикл, и будет остановлен. Javadoc: вызывает завершение цикла обработчика потока без обработки каких-либо сообщений в очереди сообщений. - person huseyin; 25.01.2016
comment
@Andromeda Доступен ли Looper.quit()scope в onDestroy() методе? - person roottraveller; 04.02.2016
comment
@ - rkm_Hodor в то время как onDestroy, просто вызовите метод yourThread.quit (), который будет обрабатывать петлитель внутри this. Но это справедливо для HandlerThreads, которые обрабатывают персонал петлителя вместо вас. Если вы создаете свой собственный поток и собственную реализацию Looper, вы должны обрабатывать свой цикл, просто добавляя метод quit () в свой поток. public boolean quit () {Looper looper = getLooper (); если (цикл! = ноль) {looper.quit (); вернуть истину; } return false; } - person huseyin; 24.02.2016
comment
Это не объясняет, почему можно использовать этот класс, только как. - person Andrew Koster; 10.05.2016
comment
Удивительно ... Кто-нибудь понимает, как отправить сообщение в LooperThread? Совершенно бесполезный пример. Все просто скопировали глупый пример из документации. - person Sever; 16.06.2020

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

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

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

Как вы, возможно, знаете, когда приложение запускается, система создает поток выполнения для приложения, называемый «основным», и приложения Android обычно работают полностью в одном потоке, по умолчанию это «основной поток». Но основная ветка - это не какая-то секретная, особенная ветка. Это просто обычный поток, похожий на потоки, которые вы создаете с помощью кода 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 будет работать в обычном потоке? Поток под названием «основной» или «UI» или что-то еще запускает ваше приложение и рисует весь UI. Итак, пользователям отображается первый экран. И что теперь? Основной поток завершается? Нет, не должно быть. Он должен подождать, пока пользователи что-то сделают, верно? Но как добиться такого поведения? Что ж, можем попробовать с Object.wait() или Thread.sleep(). Например, основной поток завершает свою первоначальную работу по отображению первого экрана и засыпает. Он просыпается, то есть прерывается, когда выбирается новое задание. Пока все хорошо, но на данный момент нам нужна структура данных, похожая на очередь, для хранения нескольких заданий. Подумайте о случае, когда пользователь последовательно касается экрана, и задача занимает больше времени для завершения. Итак, нам нужна структура данных, чтобы удерживать задания, которые должны выполняться в порядке очереди. Кроме того, вы можете себе представить, что реализация потока с постоянным выполнением и обработкой-заданием-по-прибытии с использованием прерывания непроста и приводит к сложному и часто не поддерживаемому коду. Мы бы предпочли создать новый механизм для этой цели, и в этом вся суть Looper. В официальном документе класса 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 - это класс, созданный для решения проблемы, возникающей в среде графического интерфейса. Но такого рода потребности могут возникнуть и в другой ситуации. На самом деле это довольно известный шаблон для многопоточного приложения, и вы можете узнать о нем больше в статье «Параллельное программирование на Java» Дуга Ли (особенно полезна глава 4.1.4 «Рабочие потоки». ). Кроме того, вы можете себе представить, что этот вид механизма не является уникальным в структуре Android, но для всей инфраструктуры графического интерфейса может потребоваться что-то подобное. Вы можете найти почти такой же механизм в Java Swing framework.

person 김준호    schedule 30.12.2015
comment
Это единственный ответ, который на самом деле что-либо объясняет, почему класс Looper когда-либо будет использоваться. Я не уверен, почему это не лучший ответ, три ответа с более высоким рейтингом ничего не объясняют. - person Andrew Koster; 10.05.2016
comment
@AK. Вот почему я добавил этот ответ, хотя мне показалось, что уже слишком поздно. Рад, что мой ответ помог тебе! :) - person 김준호; 10.05.2016
comment
До прочтения я был похож на Лупера ??? а теперь о да, давайте обсудим это. Спасибо, чувак, отличный ответ :) - person umerk44; 12.02.2017
comment
Быстрый вопрос. Вы заявили, что в основном потоке после извлечения всех элементов пользовательского интерфейса он переводится в спящий режим. Но предположим, что пользователь взаимодействует с кнопкой на экране, разве эта кнопка не помещается даже в основную очередь, тогда какой-то объект отправит его в правильное действие, тогда основной поток для этого действия активен, и он выполнит код для обратного вызова для этой кнопки? - person ; 27.02.2017
comment
Вао, так ясно объяснено. Интересно, почему это не принятый ответ. - person Avijeet; 16.05.2017
comment
Потрясающие. Лучше и быть не могло. - person Rishabh Dutt Sharma; 30.05.2017

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);
  } 
}
}

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

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

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

person user2834274    schedule 01.10.2013
comment
он не заблокирует ни один процесс пользовательского интерфейса, правда? - person gumuruh; 17.06.2014
comment
Благодарим за то, что вы добавили образец того, как размещать вакансии в очереди. - person Peter Lillevold; 09.01.2015
comment
Это не объясняет, почему можно использовать этот класс, только как. - person Andrew Koster; 10.05.2016
comment
Это внутренний класс SampleLooper? - person Sever; 16.06.2020

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

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

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

Looper = Thread + MessageQueue

person user542954    schedule 18.09.2013
comment
Это не объясняет, почему можно использовать этот класс, только как. - person Andrew Koster; 10.05.2016

Простейшее определение лупера и обработчика:

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

Подробная информация в общей формулировке:

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

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

Пример:

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

Узнайте больше о Looper и Handler, а также об определении Pipeline Thread:

Android Guts: введение в луперы и обработчики

person ahmadalibaloch    schedule 16.08.2016

Понимание потоков лупера

Поток Java - модуль выполнения, который был разработан для выполнения задачи в своем методе run () и завершился после этого:  введите описание изображения здесь

Но в Android есть много случаев использования, когда нам нужно поддерживать поток и ждать пользовательских вводов / событий, например. Поток пользовательского интерфейса, также известный как Main Thread.

Основной поток в Android - это поток Java, который сначала запускается JVM при запуске приложения и продолжается до тех пор, пока пользователь не решит закрыть его или не встретит необработанное исключение.

Когда приложение запускается, система создает поток выполнения для приложения, называемый «основным». Этот поток очень важен, потому что он отвечает за отправку событий соответствующим виджетам пользовательского интерфейса, включая события рисования.

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

Теперь обратите внимание на то, что хотя основным потоком является поток Java, он продолжает прослушивать пользовательские события и рисовать кадры со скоростью 60 кадров в секунду на экране, и все же он не умирает после каждого цикла. как это так?

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

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

Целью Looper является поддержание активности потока и ожидание следующего цикла ввода объекта Message для выполнения вычислений, которые в противном случае будут уничтожены после первого цикла выполнения.

Если вы хотите глубже изучить, как Looper управляет Message очередью объектов, вы можете взглянуть на исходный код Looperclass:

https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/os/Looper.java

Ниже приведен пример того, как вы можете создать Looper Thread и общаться с Activity классом, используя LocalBroadcast

class LooperThread : Thread() {

    // sendMessage success result on UI
    private fun sendServerResult(result: String) {
        val resultIntent = Intent(ServerService.ACTION)
        resultIntent.putExtra(ServerService.RESULT_CODE, Activity.RESULT_OK)
        resultIntent.putExtra(ServerService.RESULT_VALUE, result)
        LocalBroadcastManager.getInstance(AppController.getAppController()).sendBroadcast(resultIntent)
    }

    override fun run() {
        val looperIsNotPreparedInCurrentThread = Looper.myLooper() == null

        // Prepare Looper if not already prepared
        if (looperIsNotPreparedInCurrentThread) {
            Looper.prepare()
        }

        // Create a handler to handle messaged from Activity
        handler = Handler(Handler.Callback { message ->
            // Messages sent to Looper thread will be visible here
            Log.e(TAG, "Received Message" + message.data.toString())

            //message from Activity
            val result = message.data.getString(MainActivity.BUNDLE_KEY)

            // Send Result Back to activity
            sendServerResult(result)
            true
        })

        // Keep on looping till new messages arrive
        if (looperIsNotPreparedInCurrentThread) {
            Looper.loop()
        }
    }

    //Create and send a new  message to looper
    fun sendMessage(messageToSend: String) {
        //Create and post a new message to handler
        handler!!.sendMessage(createMessage(messageToSend))
    }


    // Bundle Data in message object
    private fun createMessage(messageToSend: String): Message {
        val message = Message()
        val bundle = Bundle()
        bundle.putString(MainActivity.BUNDLE_KEY, messageToSend)
        message.data = bundle
        return message
    }

    companion object {
        var handler: Handler? = null // in Android Handler should be static or leaks might occur
        private val TAG = javaClass.simpleName

    }
}

Использование:

 class MainActivity : AppCompatActivity() {

    private var looperThread: LooperThread? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start looper thread
        startLooperThread()

        // Send messages to Looper Thread
        sendMessage.setOnClickListener {

            // send random messages to looper thread
            val messageToSend = "" + Math.random()

            // post message
            looperThread!!.sendMessage(messageToSend)

        }   
    }

    override fun onResume() {
        super.onResume()

        //Register to Server Service callback
        val filterServer = IntentFilter(ServerService.ACTION)
        LocalBroadcastManager.getInstance(this).registerReceiver(serverReceiver, filterServer)

    }

    override fun onPause() {
        super.onPause()

        //Stop Server service callbacks
     LocalBroadcastManager.getInstance(this).unregisterReceiver(serverReceiver)
    }


    // Define the callback for what to do when data is received
    private val serverReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val resultCode = intent.getIntExtra(ServerService.RESULT_CODE, Activity.RESULT_CANCELED)
            if (resultCode == Activity.RESULT_OK) {
                val resultValue = intent.getStringExtra(ServerService.RESULT_VALUE)
                Log.e(MainActivity.TAG, "Server result : $resultValue")

                serverOutput.text =
                        (serverOutput.text.toString()
                                + "\n"
                                + "Received : " + resultValue)

                serverScrollView.post( { serverScrollView.fullScroll(View.FOCUS_DOWN) })
            }
        }
    }

    private fun startLooperThread() {

        // create and start a new LooperThread
        looperThread = LooperThread()
        looperThread!!.name = "Main Looper Thread"
        looperThread!!.start()

    }

    companion object {
        val BUNDLE_KEY = "handlerMsgBundle"
        private val TAG = javaClass.simpleName
    }
}

Можем ли мы использовать вместо этого Async Task или Intent Services?

  • Асинхронные задачи предназначены для выполнения короткой операции в фоновом режиме и предоставления прогресса и результатов в потоке пользовательского интерфейса. Асинхронные задачи имеют ограничения, например, вы не можете создать более 128 асинхронных задач, а ThreadPoolExecutor разрешит только до 5 асинхронных задач.

  • IntentServices также предназначены для выполнения фоновых задач в течение немного более длительного времени, и вы можете использовать LocalBroadcast для связи с Activity. Но сервисы уничтожаются после выполнения задачи. Если вы хотите, чтобы он работал в течение длительного времени, вам нужно делать такие черты, как while(true){...}.

Другие варианты использования Looper Thread:

  • Используется для двухсторонней связи сокетов, когда сервер продолжает прослушивать клиентский сокет и записывать подтверждение

  • Обработка растровых изображений в фоновом режиме. Передайте URL-адрес изображения потоку Looper, и он применит эффекты фильтра и сохранит его во временном местоположении, а затем передаст временный путь изображения.

person Hitesh Sahu    schedule 14.03.2019

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

Он реализует Thread конкретный шаблон хранения.

Только один Looper на Thread. Ключевые методы включают _6 _, _ 7_ и quit().

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

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

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

  1. Расширить Thread

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

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

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

Срок службы Thread Java закончился после завершения run() метода. Тот же поток не может быть запущен снова.

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

void prepare ()

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

void loop ()

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

void quit()

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

Вызывает завершение работы метода loop () без обработки сообщений в очереди сообщений.

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

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

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

Вам необходимо Looper быть связанным с обработчиком.

Looper, Handler и HandlerThread - это способ Android решать проблемы асинхронного программирования.

Как только у вас будет 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: тост в ветке

person Ravindra babu    schedule 31.08.2017

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

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

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

person TacB0sS    schedule 16.11.2017

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

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

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

person Thorsten    schedule 20.03.2013

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

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

Looper

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

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

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

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

Создание лупера

Поток получает 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();
      } 
  }

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

person AskNilesh    schedule 27.11.2018

Я постараюсь как можно проще объяснить назначение класса лупера. В обычном потоке Java, когда метод run завершает выполнение, мы говорим, что поток выполнил свою работу, и после этого поток больше не живет. что, если мы хотим выполнять больше задач в нашей программе с тем же потоком, который больше не живет? О, теперь проблема, не так ли? Да, потому что мы хотим выполнять больше задач, но поток больше не работает. Здесь нам на помощь приходит Looper. Looper, как следует из названия, предполагает петли. Looper - это не что иное, как бесконечный цикл внутри вашего потока. Таким образом, он поддерживает поток в течение бесконечного времени, пока мы явно не вызовем метод quit (). Вызов метода quit () в бесконечно живом потоке сделает условие ложным в бесконечном цикле внутри потока, таким образом, бесконечный цикл завершится. Итак, поток умрет или больше не будет живым. И очень важно вызвать метод quit () в нашем потоке, к которому подключен лупер, иначе они будут в вашей системе, как зомби. Так, например, если мы хотим создать фоновый поток для выполнения нескольких задач над ним. мы создадим простой поток Java и будем использовать класс Looper для подготовки цикла и присоединения подготовленного цикла к этому потоку, чтобы наш поток мог жить так долго, как мы хотим, потому что мы всегда можем вызвать quit () в любое время, когда мы хотим завершить наша ветка. Таким образом, наш петлитель будет поддерживать наш поток в рабочем состоянии, поэтому мы сможем выполнять несколько задач с одним и тем же потоком, и когда мы закончим, мы вызовем quit () для завершения потока. Что, если мы хотим, чтобы наш основной поток или поток пользовательского интерфейса отображал результаты, вычисленные фоновым потоком или потоком, отличным от пользовательского интерфейса, для некоторых элементов пользовательского интерфейса? для этой цели используется концепция обработчиков; через обработчики мы можем осуществлять межпроцессное взаимодействие или, скажем, через обработчики два потока могут взаимодействовать друг с другом. Таким образом, основной поток будет иметь связанный обработчик, а фоновый поток будет связываться с основным потоком через этот обработчик, чтобы выполнить задачу по отображению результатов, вычисленных им в некоторых элементах пользовательского интерфейса в основном потоке. Я знаю, что объясняю здесь только теорию, но постараюсь понять концепцию, потому что глубокое понимание концепции очень важно. И я публикую ссылку ниже, которая приведет вас к небольшой серии видео о Looper, Handler и HandlerThread, и я настоятельно рекомендую посмотреть ее, и все эти концепции будут прояснены там с примерами.

https://www.youtube.com/watch?v=rfLMwbOKLRk&list=PL6nth5sRD25hVezlyqlBO9dafKMc5fAU2&index=1

person Uzair Afridi    schedule 01.01.2021

Я пытаюсь привести пример на Котлине. Вот пример кода.

Во-первых, нам нужно создать экземпляр обработчика переменных из Handler (предоставленный цикл вместо стандартного), который запрашивает основной поток (Looper.getMainLooper ()).

Функция getAllCourses () должна возвращать LiveData, поэтому мы используем handler.postDelayed () для добавления в очередь сообщений и запуска через x количество миллисекунд, указанное в константе SERVICE_LATENCY_IN_MILLIS.

Пожалуйста, не стесняйтесь уточнить мои пояснения, чтобы было больше ясности.

class RemoteDataSource private constructor(private val jsonHelper: JsonHelper) {

    private val handler = Handler(Looper.getMainLooper())

    companion object {
        private const val SERVICE_LATENCY_IN_MILLIS: Long = 2000

        @Volatile
        private var instance: RemoteDataSource? = null

        fun getInstance(helper: JsonHelper): RemoteDataSource =
                instance ?: synchronized(this) {
                    RemoteDataSource(helper).apply { instance = this }
                }
    }

    fun getAllCourses(): LiveData<ApiResponse<List<CourseResponse>>> {
        EspressoIdlingResource.increment()
        val resultCourse = MutableLiveData<ApiResponse<List<CourseResponse>>>()
        handler.postDelayed({
            resultCourse.value = ApiResponse.success(jsonHelper.loadCourses())
            EspressoIdlingResource.decrement()
        }, SERVICE_LATENCY_IN_MILLIS)
        return resultCourse
    }
person Ade Trisna    schedule 07.06.2021