#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
, как показано ниже, предлагаемый подход.
-
Вы можете создать другой конструктор, который
Looper
также имеет доступ:TimeOutHandler(final SyncWorker service, Looper looper) { super(looper); mMainWeakReference = new WeakReference<>(service); }
И инициализируйте, как :
TimeOutHandler handler = new TimeOutHandler(service, Looper.getMainLooper());
-
Прямой переход
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, когда вы закончите свои асинхронные вычисления.