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

Posted

技术标签:

【中文标题】CountDownTimer:“无法在未调用 Looper.prepare() 的线程内创建处理程序”【英文标题】:CountDownTimer: "Can't create handler inside thread that has not called Looper.prepare()" 【发布时间】:2011-04-29 17:23:18 【问题描述】:

我知道之前有人问过“无法在未调用 Looper.prepare() 的线程内创建处理程序”的一般问题,但我很难理解它在这种情况下如何应用。

我正在尝试在非 UI 线程中构造一个新的 CountDownTimer,我猜这是导致此错误的原因,但我真的不明白为什么需要在主线程中使用计时器。从我所看到的来看,它看起来有一个回调处理程序,需要在具有循环器的线程中运行,而非 UI 线程默认情况下没有该循环器。看来我的选择是:1)让这个非 UI 线程有一个 Looper 或 2)在我的 UI 线程上做一些奇怪的方法来构造这个计时器,这两种方法对我来说都是愚蠢的。有人可以帮我理解其中的含义吗?

另外,有没有人知道任何有用的链接可以阐明 Looper 和 MessageQueue?我没有很好地掌握它们,我确信我已经证明了这一点。谢谢!

【问题讨论】:

【参考方案1】:

计时器不需要在 UI 线程中。但我的猜测是您正在更新 UI 以显示该线程中的倒计时。于不能那样做。

使用异步任务并更新 onProgressUpdate 中的 UI

【讨论】:

我不相信是这样的。我已经注释掉了匿名类中的所有代码,所以它在构造函数中调用了 super ,但我仍然得到同样的错误。是不是因为 CountDownTimer 有一个完成时的回调方法,而这需要由 looper “触发”?这是我希望消除的困惑。我们甚至可以将问题从我的特定问题中抽象出来——我只是想弄清楚它们是如何结合在一起的。谢谢。 哦,我想我误解了你的问题。我可以问你为什么在非 UI 线程中使用 CountdownTimer 吗?我认为CountdownTimer 的重点是能够轻松更新 UI 线程。看起来 onTick()onFinish() 应该在 UI 线程上运行。为什么不直接使用常规的 java 计时器? 我想我可以使用常规计时器。无论如何,如果我不进行任何 UI 更新,为什么 CountDownTimer 会在构造函数中爆炸? 因为每次调用 onTick() 时它都希望可能在 UI 线程上 为什么 onTick() 需要 UI 线程?这是我不明白的。为什么这个处理程序需要访问 UI 线程对我来说没有意义。是否所有需要中断的异步方法都通过 UI 线程工作?感谢您的帮助。【参考方案2】:

必须在 UI 线程上创建 CountDownTimer 的实例。

如果您有自定义类对象:

public class MyTimer extends CountDownTimer
    public MyTimer(...)
         super(duration,interval);
    
    //... other code ...//

对象的构造必须在UI线程上运行

MyTimer mTimer = new MyTimer(...);   //can throw RuntimeException
                                    // with Looper.prepare() issue if
                                    // caller isn't UI thread

如果多个线程正在创建和销毁计时器,请通过执行以下操作确保它是在 UI 线程上创建的:

MyActivity.runOnUiThread( new Runnable()
     public void run()
          mTimer = new MyTimer(...);
     
);

但请注意上面的代码段如何需要引用您的 Activity 和类成员变量 mTimer

【讨论】:

CountdownTimer 不需要在 UI 线程上创建。 CountdownTimer 创建一个 Handler,它需要 Looper 提供的消息循环。 是的。在 android API 23 上测试。如果我在后台线程上创建它,我会得到臭名昭著的 Looper.prepare 异常。不过,我的自定义类会用剩余时间更新 TextView。

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

使用 CountDownTimer 更新 ProgressBar

XX 格式的 CountDownTimer 秒数

如何向 CountDownTimer 添加闹钟?

Android CountDownTimer的使用

Android CountDownTimer的使用

Android CountDownTimer的使用