场景:在一个Activity中创建一个Handler进行收发Message消息
public class TestActivity extends Activity {
private Handler handler = new Handler(){
// Handler消息回调
public void handleMessage(Message msg) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
// 主线程中发Handler消息1
handler.sendEmptyMessage(1);
// 主线程中发Handler消息2
handler.post(new Runnable() {
@Override
public void run() {
handler.sendEmptyMessage(1);
}
});
// 子线程中发Handler消息
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare(); //
handler.sendEmptyMessage(1);
Looper.loop(); //
}
}, "child thread").start();
}
}
原理:某个Acitivty的UiThread启动并创建了1个Looper对象,在构造函数Looper()初始化时构造MessageQueue消息队列,并自动执行loop()方法开始循环处理Message消息,其实就是通过msg的target对象Handler回调dispatchMessage()方法。
Looper中
MessageQueue mQueue;//消息队列
// 构造Looper
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);// 创建Looper对应的消息队列
mRun = true;
mThread = Thread.currentThread();//线程初始化为本线程
}
// 启动loop方法,在此循环处理Message消息
public static void loop() {
final Looper me = myLooper(); //获得当前线程的Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; //获得Looper里的MessageQueue消息队列
// 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 (;;) { // 无限循环MessageQueue消息队列,直到退出
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);//通过msg的target对象回调dispatchMessage(),同handleMessage()
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回调dispatchMessage()
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
// 回调
private static void handleCallback(Message message) {
message.callback.run();
}
这时,我们构建了一个Handler对象并初始化,当我们调用Handler对象发送消息时,其实只是将Message或Runnable压入自己所在的当前线程Thead中的Looper中的MessageQueue队列。每个线程只能对应一个Looper,除主线程外,Android中的线程默认是没有开启Looper的,在子线程中发送Message消息前需要先执行Looper.prepare()方法检测当前子线程是否已存在Looper对象,消息发送完后,执行Looper.loop()方法通知循环处理该Looper下的MessageQueue消息队列
// Handler:发送Runnable
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
其实Runnable最后还是转化成Message消息
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
// Handler:发送Message
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
// Handler:把Message压入MessageQueue队列
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; //把msg的目标设为自己,也就是说回调自己的方法handleMessage();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
// 子线程需要手动调用loop()
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
handler.sendEmptyMessage(1);
Looper.loop();
}
}, "just_do_it").start();
// Looper prepare()方法,looper()同上
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) { // 确保1个线程里只能有1个Looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed)); // 在当前线程中创建对应的Looper
}
// 主线程不需要
handler.post(new Runnable() {
@Override
public void run() {
handler.sendEmptyMessage(1);
}
});