Android中线程的通信机制:消息机制(二)
在上一节中我们提到了MessageQueue和Looper,那么这一节中我们就说说这两个东东吧!
一般在大家默认的情况下,handler时在主线程中处理消息,即可以更新UI
一般正常我们的代码是handler时在主线程中创建
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler(new InnerHandlerCallback());
sendMessage();
}
private class InnerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
return false;
}
}
private void sendMessage(){
new Thread() {
public void run() {
handler.sendEmptyMessage(0);
}
}.start();
}
这里我们将提到handler在子线程中创建
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread() {
public void run() {
handler = new Handler(new InnerHandlerCallback());
}
}.start();
sendMessage();
}
private class InnerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
return false;
}
}
private void sendMessage(){
new Thread() {
public void run() {
handler.sendEmptyMessage(0);
}
}.start();
}
但是程序在这里会报错,提示在没有Looper.prepare()情况下子线程中不能创建handler
所以我们为了解决错误就根据错误提示进行操作
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread() {
public void run() {
// 解决错误:在子线程中创建Handler之前,必须调用Looper.prepare()
Looper.prepare();
handler = new Handler(new InnerHandlerCallback());
Looper.loop();
}
}.start();
sendMessage();
}
private class InnerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
return false;
}
}
private void sendMessage(){
new Thread() {
public void run() {
handler.sendEmptyMessage(0);
}
}.start();
}
所以我们在子线程中不可以直接创建handler,而是要先调用Looper.perpare()方法,并且还要调用Looper的loop()方法去轮询消息队列,取出消息交给handler处理。但是在这里会又有疑问,为什么主线程不调用perpare()和loop()方法,然而handler也能正常的接收消息呢?其实这里主线程已经存在调用了prepare()和loop()方法的Looper,所以主线程中创建handler的时候就不需要考虑Looper的问题了。
这里还需要注意的一个问题不是handler在哪个线程创建出来的就在哪个线程处理消息。而是Handler在哪个线程处理消息,取决于该Handler对象关联到的哪个线程的Looper对象。也就是说,如果子线程创建的Handler,关联到的是主线程的Looper对象,该Handler会在主线程处理消息。
获取looper
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread() {
public void run() {
// 解决错误:在子线程中创建Handler之前,必须调用Looper.prepare()
Looper.prepare();
情况1 获取当前线程的Looper
handler = new Handler(Looper.myLooper(),new InnerHandlerCallback());
情况2 获取主线程线的Looper
handler = new Handler(Looper.getMainLooper(),new InnerHandlerCallback());
// 使Looper轮询
Looper.loop();
}
}.start();
sendMessage();
}
Handler被重载多次,所以在创建的时候我们可指定Looper,也可不指定Looper。如果在没有显式指定Looper对象的时候,那么系统会默认创建Handler对象的线程Looper,也就是说:在哪个线程创建Handler,就在哪个线程处理消息。指定的话就由指定的Looper决定。