之前有写过一篇文章 记一次Handler的优化 ,当时并未详细的讲解Handler的线程切换功能。遂写下这篇文章,对其进行补充。
那么这一篇不得的提及到另外一个重要的类Looper。提取了Looper类中几段重要之处进行分析,其实线程切换真的很简单。
public final class Looper{
......
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop(){
// 看方法上的注释也能明白为何线程能够切换,因为handler发送的消息在创建handler关联的Looper对象所在线程被消费
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对象中的消息队列
// 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 阻塞获取Looper队列中的消息
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
final Printer logging = me.mLogging;
if(logging != null){
logging.println(">>>>> Dispatching to "+msg.target+" "+
msg.callback+": "+msg.what);
}
final longtraceTag = me.mTraceTag;
if(traceTag !=0 && Trace.isTagEnabled(traceTag)){
Trace.traceBegin(traceTag,msg.target.getTraceName(msg));
}
try{
msg.target.dispatchMessage(msg);// 分发消息给发送消息的handler处理
}finally{
if(traceTag != 0){
Trace.traceEnd(traceTag);
}
}
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.recycleUnchecked();
}
}
网友评论