[英]Why do I get a “Can't create handler inside a thread that has not called Looper.prepare()” with android.os.CountDownTimer?
[英]Android: Why can't I create a handler in new thread
我在新线程中创建处理程序时遇到问题。 这是我的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler();
}
}).start();
}
但它引起了错误! 有人可以向我解释一下吗? 非常感谢!
以下是我的错误的详细信息:
09-17 18:05:29.484: E/AndroidRuntime(810): FATAL EXCEPTION: Thread-75
09-17 18:05:29.484: E/AndroidRuntime(810): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-17 18:05:29.484: E/AndroidRuntime(810): at android.os.Handler.<init>(Handler.java:197)
09-17 18:05:29.484: E/AndroidRuntime(810): at android.os.Handler.<init>(Handler.java:111)
09-17 18:05:29.484: E/AndroidRuntime(810): at com.example.handler.MainActivity$1.run(MainActivity.java:57)
09-17 18:05:29.484: E/AndroidRuntime(810): at java.lang.Thread.run(Thread.java:856)
你也可以像这样使用HandlerThread
:
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
HandlerThread
有一个与它们相关联的Looper
,所以这不会引发异常。
Thread的lifecycle
在run方法返回后立即完成。 但是由于您在此thread
中创建了一个Handler
,因此Handler需要运行该线程才能接收消息并处理它们。
因此,为此,run方法不应该退出。 因此,您需要一个Looper无限期地等待并处理到达Handler的消息。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Handler handler = new Handler();
Looper.loop();
}
}).start();
简答:因为您尝试连接处理程序的线程没有弯针。 所以Handler类的构造函数抛出异常。 您可以使用HandlerThread类,这只是Android框架提供的一个方便的类。
请阅读以下内容,了解引擎盖下发生的事情。
让我们首先尝试单独讨论所有部分。
一个。 线程只是一个执行流程。 默认情况下,线程只是执行其runnable(如果提供)或调用其run方法。 在调用新的Thread.start()时。 当run方法执行run(){----}中写入的所有语句时,线程就会死掉并且Gc'd。
湾 Android中有一个Looper的概念。 这基本上使线程成为阻塞线程。 简单地说就是不让线程死掉。 它进入阻塞状态并等待更多消息再次恢复执行。
下面是你如何设置一个阻塞线程,即一个带有looper的线程。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Looper.loop();
}
}).start();
这里创建了一个线程,它不仅在执行Looper.loop()语句后死掉。 相反,它循环并进入阻塞状态。 现在你必须要问阻塞状态是什么意思,线程将如何脱离阻塞状态? 我现在如何最终发布这个帖子? 这就是Handler的用武之地
一个。 它总是将自身附加到线程的Looper上,在该线程上创建其实例。
湾 然后它处理它附加的线程的那些消息。
将线程和处理程序放在一起。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
handler = new Handler();
Looper.loop();
}
}).start();
一个。 处理程序如何附加到这个新创建的线程。 湾 该线程被设置为阻塞循环线程。 所以这不会死。
现在,我们可以1.在此处理程序上发送消息。 2.在此处理程序上发布runnable。
它们都将在附加的线程上执行。
您可以选择扩展Handler类并实现方法handleMessage(Message msg)。 或者您只是在处理程序类的构造函数中提供Handler.Callback的实现。 无论哪种方式,都会在附加的线程上调用handleMessage(Messages msg)。
要退出线程,您可以发送特定类型的消息类型,并在收到该消息后,您只需调用Looper.myLooper()。quit()
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
if(msg.what == -1){
Looper.myLooper().quit();
}
}
};
Looper.loop();
}
}
我希望它有助于理解整体概念。
Handler需要在Looper线程中初始化,或者给它一个Looper。
根据您的要求,您可以将线程设置为Looper,如下所示:
new Thread(new Runnable() {
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}).start();
由于Looper位于后台线程中,因此无法更新UI。 您可以替代地从另一个线程向Handler提供一个Looper - 在此示例中,Handler可用于更新UI:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
}
}).start();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.