Разряжает ли android.os.Looper батарею?

Наверное глупый вопрос, но все же...

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

Быстро ли разряжает батарею Android длительное использование android.os.Looper?

Из исходный код

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

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

        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        msg.target.dispatchMessage(msg);

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycle();
    }
}

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

Кто-нибудь знает, это всего лишь миф? Или мне подобрать какой-то другой класс для решения моей задачи?

Спасибо за уделенное время.


person UnknownJoe    schedule 06.09.2013    source источник


Ответы (2)


Хорошо. Это зависит от того, сколько сообщений и как часто вы будете отправлять в этот лупер. Хотя он работает в бесконечном цикле, эта реализация будет ждать queue.next() следующего сообщения для продолжения. В режиме ожидания петлитель ничего не потребляет. Если вы собираетесь отправлять много сообщений постоянно, то не имеет значения, используете ли вы лупер или что-то еще. Ваш код будет работать и потреблять заряд батареи.

person sergej shafarenka    schedule 06.09.2013
comment
grepcode.com/file_/repository.grepcode.com/java/ext/ В методе .next() есть вызов nativePollOnce(...). Блокирует ли этот собственный метод поток до тех пор, пока не придет следующее сообщение? - person UnknownJoe; 06.09.2013
comment
Да, это блокирует поток. Если у вас есть запланированное сообщение для обработки позже (например, оно было добавлено методом postDelayed()), то оно блокирует поток с тайм-аутом, определяемым этой задержкой. Я использую луперы для фоновой обработки в каждом из моих приложений, и все они очень экономичны в отношении батареи. С ними никаких проблем ;) play.google.com/store /apps/details?id=com.hb.settings - person sergej shafarenka; 06.09.2013

каждый поток пользовательского интерфейса имеет Looper, так что это не такой зверь, см.: queue.next(); // может заблокироваться, здесь проходит большая часть времени

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

person pskink    schedule 06.09.2013
comment
Да, я забыл добавить. Мой Looper привязан к потоку, отличному от пользовательского интерфейса. Большое спасибо за ваш ответ. - person UnknownJoe; 06.09.2013
comment
Хорошо, вы можете поиграться с методами prepare() и loop() в новом потоке, но HandlerThread сделает эту работу за вас. - person pskink; 06.09.2013