之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码:
packagecn.lixyz.handlertest;importandroid.app.Activity;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Message;importandroid.util.Log;importandroid.view.View;importandroid.widget.Button;public class MainActivity extendsActivity {privateButton button;privateHandler handler;private int i = 0;
@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button);
button.setOnClickListener(newView.OnClickListener() {
@Overridepublic voidonClick(View v) {
Log.d("TTTT", "onClick:" +Thread.currentThread().getName());
Message msg=handler.obtainMessage();
handler.sendMessage(msg);
}
});
WorkerThread wt= newWorkerThread();
wt.start();
}class WorkerThread extendsThread {
@Overridepublic voidrun() {super.run();
handler= newHandler() {
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);
Log.d("TTTT", "收到了消息对象");
}
};
}
}
}
MainActivity.java
activity_main.xml
上面的问题貌似没什么错误,但运行时却出错
抛出异常:
09-17 04:01:31.655 15854-15869/? E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-120
Process: cn.lixyz.handlertest, PID: 15854
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:200)
at android.os.Handler.(Handler.java:114)
at cn.lixyz.handlertest.MainActivity$WorkerThread$1.(MainActivity.java:48)
at cn.lixyz.handlertest.MainActivity$WorkerThread.run(MainActivity.java:48)
提示我们没有调用Looper.prepare(),无法创建线程,原因是非主线程中默认是没有创建Looper对象的,需要先调用Looper.prepare()启用Looper。修改一下上面的代码。
packagecn.lixyz.handlertest;importandroid.app.Activity;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Looper;importandroid.os.Message;importandroid.util.Log;importandroid.view.View;importandroid.widget.Button;public class MainActivity extendsActivity {privateButton button;privateHandler handler;
@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button) findViewById(R.id.button);
button.setOnClickListener(newView.OnClickListener() {
@Overridepublic voidonClick(View v) {
Message msg=handler.obtainMessage();
msg.what= 100;
handler.sendMessage(msg);
Log.d("TTTT", "sendMessage:" +Thread.currentThread().getName());
}
});
WorkerThread wt= newWorkerThread();
wt.start();
}class WorkerThread extendsThread {
@Overridepublic voidrun() {super.run();
Looper.prepare();
handler= newHandler() {
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);
Log.d("TTTT", "handleMessage:" +Thread.currentThread().getName());int i =msg.what;
Log.d("TTTT", "收到了消息对象:" +i);
}
};
Looper.loop();
}
}
}
MainActivity.java
activity_main.xml
运行结果:
09-17 04:29:48.669 28397-28397/cn.lixyz.handlertest D/TTTT﹕ sendMessage:main09-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ handleMessage:Thread-141
09-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ 收到了消息对象:100
上面代码表示,消息是从MainThread发送的,WorkerThread接收到了消息。
PS:非UI线程默认是没有创建Looper对象的,所以需要主线程向子线程传递消息时,需创建Looper对象并启动循环,子线程才可以循环着从MaessageQueue中取出消息。