无法在未在WorkManager中调用Looper.prepare()的线程内创建处理程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法在未在WorkManager中调用Looper.prepare()的线程内创建处理程序相关的知识,希望对你有一定的参考价值。

我正在尝试为定期后台操作实现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的方式做到这一点。

答案

当你创建了扩展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()初始化父(超)类的构造函数&在我们的例子中,我们将Looper作为参数传递给super将使用构造函数Handler(Looper looper)初始化Handler,该构造函数之前是Handler()(空或默认构造函数)。

注意:问题是Handler类有多个构造函数,其中一个接受Looper,用于将Handler切换到提供的特定线程。

另一答案

请记住,即使您成功实现了Handler,您的代码也无法按预期工作。一旦从Worker类返回结果,您的进程就有资格停止。你真正想要的是一个ListenableWorker,并在你完成异步计算后完成你的ListenableFuture。

以上是关于无法在未在WorkManager中调用Looper.prepare()的线程内创建处理程序的主要内容,如果未能解决你的问题,请参考以下文章

CountDownTimer:“无法在未调用 Looper.prepare() 的线程内创建处理程序”

无法在未调用 Looper 准备的线程内创建处理程序 [重复]

无法在未调用 Looper 的线程内创建处理程序 [重复]

无法在未调用 Looper.prepare()3 的线程内创建处理程序

无法在未调用 Looper.prepare() 的线程内创建处理程序

RxJava 无法在未调用 Looper.prepare() 的线程内创建处理程序