Android开发首页投稿(暂停使用,暂停投稿)Android技术知识

Handler,Looper,MessageQueue原理分析

2016-08-11  本文已影响218人  HarryXR

Handler机制在android开发中经常使用,一直没搞明白Handler,Looper,MessageQueue它们之间的关系,此次就从源码的角度分析一下

1. 简述

Looper负责创建MessageQueue,然后进入无限循环体中不断从MessageQueue取出消息,触发消息的分发处理,而Handler负责发送消息

2.源码分析

prepare()方法:

private static void prepare(boolean quitAllowed) { 
  if (sThreadLocal.get() != null) {       
    throw new RuntimeException("Only one Looper may be created per thread");   
 }    
  sThreadLocal.set(new Looper(quitAllowed));
}

从上面看出ThreadLocal存储了Looper对象,而且此方法不能运行两次,否则抛出异常.

loop()方法:
>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; //获得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 (;;) { //此处无限循环,取出消息
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); //分发处理消息
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();
}}

首先myLooper()从ThreadLocal中获取Looper对象,如果looper为null则抛出异常,也说明prepare()在loop()之前运行
>public static Looper myLooper() {
return sThreadLocal.get();
}

下一步是拿到MessageQueue,即me.Queue;
再进入开头所说的无限循环,取出消息msg;
最后就是msg.target.dispatchMessage(msg),分发处理,target就是Handler.

概括Looper作用:

  1. 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
  2. loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
    下面就该Handler发送消息了
  1. Handler与MessageQueue绑定
    看Handler构造方法

    public Handler() {  
        this(null, false);  
     }  
     public Handler(Callback callback, boolean async) {  
     if (FIND_POTENTIAL_LEAKS) {  
         final Class<? extends Handler> klass = getClass();  
         if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
                 (klass.getModifiers() & Modifier.STATIC) == 0) {  
             Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
                 klass.getCanonicalName());  
         }  
     }  
     mLooper = Looper.myLooper();  
     if (mLooper == null) {  
         throw new RuntimeException(  
             "Can't create handler inside thread that has not called Looper.prepare()");  
     }  
     mQueue = mLooper.mQueue;  
     mCallback = callback;  
     mAsynchronous = async;  
    }  
    

通过Looper.myLooper()获取了当前线程保存的Looper实例,然后又获取了这个Looper实例中保存的MessageQueue(消息队列),这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了

下面看发送消息的方法

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);  
  }                                                                                                                   

nqueueMessage中首先为msg.target赋值为this,也就是把当前的handler作为msg的target属性。最终会调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。

现在已经很清楚了Looper会调用prepare()和loop()方法,在当前执行的线程中保存一个Looper实例,这个实例会保存一个MessageQueue对象,然后当前线程进入一个无限循环中去,不断从MessageQueue中读取Handler发来的消息。然后再回调创建这个消息的handler中的dispathMessage方法,下面我们赶快去看一看这个方法:

public void dispatchMessage(Message msg) {  
    if (msg.callback != null) {  
        handleCallback(msg);  
    } else {  
        if (mCallback != null) {  
            if (mCallback.handleMessage(msg)) {  
                return;  
            }  
        }  
        handleMessage(msg);  
    }  
}  

可以看到调用了 handleMessage(msg)方法;

 public void handleMessage(Message msg) {  
}  

这是一个空方法,因为消息的最终回调都是我们自己实现的,在handler中实现handleMessage();

好了,现在总结一下整个流程:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。


   private static Message getPostMessage(Runnable r) {  
    Message m = Message.obtain();  
    m.callback = r;  
    return m;  
    }  

可以看到就是将runnable设置为msg.callback,下面和handler.sendMessage一样,最终到dispatchMessage:

public void dispatchMessage(Message msg) {  
   if (msg.callback != null) {  
       handleCallback(msg);  
   } else {  
       if (mCallback != null) {  
           if (mCallback.handleMessage(msg)) {  
               return;  
           }  
       }  
       handleMessage(msg);  
   }  
 }  

此时因msg.callback != null,所以直接执行handleCallback(msg);

private static void handleCallback(Message message) {        
    message.callback.run();
  }  

handleCallback()其实就只执行的Runnable的run方法,所以handler.post不会另开线程;
嗯,到此就全部结束了,相信对Handler,Looper,MessageQueue之间的关系都有了解了吧.

上一篇下一篇

猜你喜欢

热点阅读