Не удается создать обработчик внутри потока, который не вызвал Looper.prepare () в WorkManager - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь реализовать WorkManager для периодической фоновой операции. Я получаю общую ошибку при попытке использовать Handler в Worker. Я знаю, что ошибка говорит о том, что мне нужно позвонить Looper.prepare(), потому что я нахожусь не в том потоке, но я не знаю, как это сделать.

Это код, который я использую:

public class SyncWorker extends Worker {

    private static TimeOutHandler mTimeOutHandler;

    public SyncWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
        mTimeOutHandler = new TimeOutHandler(this);
    }

    @Override
    public Result doWork() {    
        return Result.success();
    }

    private static class TimeOutHandler extends Handler {
        private final WeakReference<SyncWorker> mMainWeakReference;

        //this is where the error is thrown
        TimeOutHandler(final SyncWorker service) {
            mMainWeakReference = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(final Message msg) {
            final SyncWorker service = mMainWeakReference.get();

            if (service != null) {
                switch (msg.what) {
                    case MESSAGE_CONNECTIVITY_TIMEOUT:
                        mTimeOutHandler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT);
                        break;
                }
            }
        }
    }
}

Handler handler = new Handler(Looper.getMainLooper());

Я провел некоторые исследования, и одним из предложенных решений является использование:

Handler handler = new Handler(Looper.getMainLooper());

но я не знаю, как сделать это с тем, как я расширяю Handler.

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

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

  1. Вы можете создать другой конструктор, который также обращается к Looper:

    TimeOutHandler(final SyncWorker service, Looper looper) {
        super(looper);
        mMainWeakReference = new WeakReference<>(service);
    }
    

    И инициализировать как:

    TimeOutHandler handler = new TimeOutHandler(service, Looper.getMainLooper());
    
  2. Непосредственно передавая Looper первичному конструктору:

    TimeOutHandler(final SyncWorker service) {
        super(Looper.getMainLooper());
        mMainWeakReference = new WeakReference<>(service);
    }
    

Таким образом, вызов super () инициализирует конструктор родительского (super) класса, и в нашем случае мы передаем Looper в качестве параметра super , который будет инициализирован Обработчик с конструктором Handler(Looper looper), который ранее был Handler() (пустой конструктор или конструктор по умолчанию) .

Примечание: Дело в том, что Обработчик Класс имеет несколько конструкторов, из которых один принимает Looper, который предоставляется для переключения Handler на конкретный предоставленный поток .

0 голосов
/ 13 апреля 2019

Имейте в виду, что ваш код не будет работать так, как вы ожидаете, даже если вы успешно внедрите обработчик. Ваш процесс может быть остановлен, как только вы вернете Результат из вашего класса Worker. То, что вы действительно хотите, это ListenableWorker и завершить ваше ListenableFuture, когда вы закончите с асинхронным вычислением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...