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

#android #android-handler #android-workmanager

#Android #android-обработчик #android-workmanager

Вопрос:

Я пытаюсь реализовать a WorkManager для периодической фоновой операции. Я получаю распространенную ошибку при попытке использовать a 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 .

Комментарии:

1. Внутри вашего TimeOutHandler конструктора поместите это в самую первую строку super(Looper.getMainLooper()); .

2. черт, я знал, что мне не хватало чего-то простого. Спасибо. Если вы хотите указать это в качестве ответа, я приму его, чтобы вы получили кредит. Спасибо.

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

Ответ №1:

Когда вы создали класс расширения 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() (пустой или конструктор по умолчанию).

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

Комментарии:

1. у меня не получилось

Ответ №2:

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