петлители в java против потока без петлителя и правильный способ остановить петлитель?

Мой вопрос касается петлителей Java, а также того, как правильно их остановить.

Допустим, у меня есть поток, определенный примерно так:

    class NoLooperThread extends Thread{
        @Override
        public void run(){

            Thread.sleep(2000);

        }
}

а у меня есть еще нитка почти такая же но с петлителем:

class LooperThread extends Thread{

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

        Thread.sleep(2000);

        Looper.loop();
    }
}

Теперь, если я это сделаю: new NoLooperThread().start(); я хочу знать, что через 2 секунды этот поток потенциально умрет, но если я это сделаю: new LooperThread().start(); поток продолжает блокироваться навсегда? мое предположение верно?

и как мне остановить эту ветку? я знаю, что мне нужно позвонить Looper.myLooper().quit();, чтобы остановить блокировку, но как лучше всего это сделать? я должен отправить сообщение через обработчик, чтобы остановить его?

Итак, у Looper две цели: он создает очередь сообщений, но также поддерживает поток сообщений. Верно ли и это предположение?

Мои вопросы приходят после прочтения вопроса SO здесь


person j2emanue    schedule 16.12.2015    source источник


Ответы (1)


После собственных проб и ошибок и исследований я решил поделиться тем, что узнал о луперах. В Android основной поток уже имеет подготовленный петлитель. Таким образом, мы можем создать обработчик для прослушивания сообщений прямо в основном потоке, и нам никогда не придется беспокоиться о зацикливании. Но если мы создадим еще один поток за пределами основного потока, например, так:

      class LooperThread extends Thread{
int count=0;
        int border=100;
        @Override
        public void run(){
           Looper.prepare();

            looperHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Log.i("HANDLER", "MyLooperThread called");
                    Bundle data = msg.getData();
                    if (data != null) {
                        count++;
                        if (count >= border) {
                            mainHandler.sendEmptyMessage(count);
                            count = 0;
                        }
                    }
                }
            };

           Looper.loop();
        }
    }
LooperThread.start();

, то мы ДОЛЖНЫ подготовить зацикливатель, иначе обработчик не сможет работать и не сможет обрабатывать сообщения. Обработчику нужен петлитель! Так что это было мое замешательство относительно того, почему Looper.prepare() не вызывался в основном потоке Android при использовании обработчика, но на самом деле он вызывается для нас.

Looper предназначен для передачи сообщений между потоками. Вы бы никогда не использовали его в asychTask, поскольку Android уже позаботился о вас. Вот почему в asyncTask onPreExecute (поток пользовательского интерфейса) -отправляет сообщения в doInBackground (фоновый поток), который затем отправляет сообщения в onPostExecute (снова поток пользовательского интерфейса). Он использует цикл для передачи сообщений с обработчиками.

Что касается выхода из Лупера, я не думаю, что когда-либо захочу этого, я бы оставил поток работающим, потому что это тип потока сообщений, который я обычно создавал, подготавливая цикл. Я хочу активно ставить сообщения в очередь на протяжении всего жизненного цикла приложения. По моему мнению, я позволю ему выйти самостоятельно, когда приложение умрет.

person j2emanue    schedule 16.12.2015
comment
Я думаю, что хорошей практикой является использование класса HandlerThread (который находится в android.os) вместо чистого потока, поскольку он подготовит для вас цикл с вызовом его метода HandlerThread.start(). Кроме того, вы можете остановить этот поток с помощью HandlerTread.quit(). - person Myroslav Kolodii; 19.11.2019
comment
да, это отличная абстракция, но вопрос был именно о луперах. - person j2emanue; 20.11.2019