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() 的线程内创建处理程序”的主要内容,如果未能解决你的问题,请参考以下文章