开发android游戏的时候,相拥Toast测试一下数据,报错了。
05-26 21:15:56.681: W/System.err(14558): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-26 21:15:56.681: W/System.err(14558): at android.os.Handler.<init>(Handler.java:121)
05-26 21:15:56.691: W/System.err(14558): at android.widget.Toast$TN.<init>(Toast.java:335)
05-26 21:15:56.691: W/System.err(14558): at android.widget.Toast.<init>(Toast.java:101)
05-26 21:15:56.691: W/System.err(14558): at android.widget.Toast.makeText(Toast.java:248)
google了一下,找到了答案:(原理:Toast里面需要一个handler来处理内部的消息)
解决办法:
1)、使用Handler
// 声明一个Handler对象
private static Handler handler=new Handler();
// 新启动一个子线程
new Thread(new Runnable() {
@Override
public void run() {
// 使用post方式加到主线程的消息队列中
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),
"test",Toast.LENGTH_LONG).show();
}
});
}
}).start();
2)、使用Looper . prepare() 和 Looper . loop()Looper.prepare()源码:(保证只有一个Looper)
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper.loop()源码:(loop()方法使用一个死循环不断支取MessageQueue中的消息,并取出消息分给该消息对应的Handler进行处理)public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
其实,Handler指定MessageQueue发送消息,而MessageQueue有Looper负责管理的。有Looper的构造函数可以看出。
在线程中使用Handler的步骤如:
调用Looper的prepare()创建当前线程的Looper对象(only one),创建对象时会创建与之对应的MessageQueue。有了MessageQueue就可以给主线程传递message了,
然后调用Handler的handleMessage(),处理对应的事件,操作主线程的UI等。然后调用Looper.loop()启动Looper。