Handler的工作主要包含消息的发送和接受过程。发送过程通过post的一系列方法和send的一系列方法来实现,post的一系列方法最终是通过send的一系列方法来实现的。发送一条消息的典型过程如下:
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue,Message msg,long uptimeMillis){
msg.target=this;
if(mAsynchronous){
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg,uptimeMillis);
}
可以发现,Handler发送消息的过程仅仅是向消息队列中插入了一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到消息后就开始处理了,最终由Looper交由Handler处理,即Handler的dispatchMessage方法会被调用,这时Handler就进入了处理消息的阶段。dispatchMessage的实现如下所示。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//Message的callback是一个Runnable,
//也就是Handler的 post方法所传递的Runnable参数
handleCallback(msg);
} else {
//如果给Handler设置了Callback的实现,
//则调用Callback的handleMessage(msg)
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//调用Handler的handleMessage方法来处理消息,
//该Handler子类需重写handlerMessage(msg)方法
handleMessage(msg);
}
}
Handler处理消息的过程如下:
首先,检查Message的callback是否为null,不为null就通过handleCallback来处理消息。Message的callback是一个Runnable对象,实际上就是Handler的post方法所传递的Runnable参数。handleCallback的逻辑也是很简单,如下所示。
private static void handleCallback(Message message) {
message.callback.run();
}
其次,检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理消息。Callback是个接口,它的定义如下:
public interface Callback {
public boolean handleMessage(Message msg);
}
//默认空实现
public void handleMessage(Message msg) {
}
Handler还有一个特殊的构造方法,可以指定一个特殊的Looper来构造Handler。
public Handler(Looper looper) {
this(looper, null, false);
}
Handler创建需要Looper,否则会抛出异常,默认获取当前线程的Looper。主线程也就是ActivityThread会自动创建Looper,其他线程如果需要Looper均需要手动创建。
在子线程中是否可以创建一个Handler,仅仅通知线程呢?
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "hadler msg", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();
很遗憾,会报错:
01-12 02:49:31.814: E/AndroidRuntime(2226): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(),需要looper.prepare().
new Thread(new Runnable() {
public void run() {
Looper.prepare(); // 此处获取到当前线程的Looper,并且prepare()
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();
1、Looper.prepare()是给这个Thread创建Looper对象,一个Thead只有一个Looper对象。
2、Looper对象需要一个MessageQueue对象一个Looper实例也只有一个MessageQueue。
3、调用Looper.loop(); 不断遍历MessageQueue中是否有消息。
4、Handler 作用是发消息到MessageQueue,从而回掉Handler 的HandleMessage的回掉方法。
new Thread(new Runnable() {
public void run() {
Looper.prepare();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
Looper.loop();
};
}).start();
这样就Ok了。
方法二:获取主线程的looper,或者说是UI线程的looper
这个方法简单粗暴,不过和上面的方法不一样的是,这个是通过主线程的looper来实现的
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper()){ // 区别在这!!!!
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();
以上就是在子线程new handler的一些说明,有什么错误,请同学留言。