Handler,Message,Looper的那一点事儿

来源:互联网 发布:中国特色社会主义知乎 编辑:程序博客网 时间:2024/06/18 17:26

Looper有关键三个方法:构造方法,prepare(),loop().

Looper中维护一个MessageQueue。

MessageQueue是一个消息队列。用来管理消息。

Handle用于发出消息,以及处理message。

Looper的prepare的代码

  1. public static final void prepare() {  
  2.         if (sThreadLocal.get() != null) {  
  3.             throw new RuntimeException("Only one Looper may be created per thread");  
  4.         }  
  5.         sThreadLocal.set(new Looper(true));  
  6. }  
里面有一个sThreadLocal.set(new Looper(true)).sThreadLocal是一个ThreadLocal类型的变量ThreadLocal是一个关于创建线程局部变量的类。通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。所以sThreadLocal里面保存了一个Looper的实例。

我们看一下Looper的构造方法:

[java] view plain copy
  1. private Looper(boolean quitAllowed) {  
  2.         mQueue = new MessageQueue(quitAllowed);  
  3.         mRun = true;  
  4.         mThread = Thread.currentThread();  
  5. }  
在这个构造方法中已经创建了MessageQueue。也就是说Looper.prepare() 方法,生成了一个Looper对象,同时生成了这个Looper对象中的MessageQueue。

我们来看看Looper.loop()方法。

  1. public static void loop() {  
  2.         final Looper me = myLooper();  
  3.         if (me == null) {  
  4.             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  5.         }  
  6.         final MessageQueue queue = me.mQueue;  
  7.   
  8.         // Make sure the identity of this thread is that of the local process,  
  9.         // and keep track of what that identity token actually is.  
  10.         Binder.clearCallingIdentity();  
  11.         final long ident = Binder.clearCallingIdentity();  
  12.   
  13.         for (;;) {  
  14.             Message msg = queue.next(); // might block  
  15.             if (msg == null) {  
  16.                 // No message indicates that the message queue is quitting.  
  17.                 return;  
  18.             }  
  19.   
  20.             // This must be in a local variable, in case a UI event sets the logger  
  21.             Printer logging = me.mLogging;  
  22.             if (logging != null) {  
  23.                 logging.println(">>>>> Dispatching to " + msg.target + " " +  
  24.                         msg.callback + ": " + msg.what);  
  25.             }  
  26.   
  27.             msg.target.dispatchMessage(msg);  
  28.   
  29.             if (logging != null) {  
  30.                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
  31.             }  
  32.   
  33.             // Make sure that during the course of dispatching the  
  34.             // identity of the thread wasn't corrupted.  
  35.             final long newIdent = Binder.clearCallingIdentity();  
  36.             if (ident != newIdent) {  
  37.                 Log.wtf(TAG, "Thread identity changed from 0x"  
  38.                         + Long.toHexString(ident) + " to 0x"  
  39.                         + Long.toHexString(newIdent) + " while dispatching to "  
  40.                         + msg.target.getClass().getName() + " "  
  41.                         + msg.callback + " what=" + msg.what);  
  42.             }  
  43.   
  44.             msg.recycle();  
  45.         }  
  46. }  

上面的第二行final Looper me = myLooper(); 
具体代码是
public static Looper myLooper() {
return sThreadLocal.get();
} 
也就是取出咱们放在sThreadLocal中的Looper.也就是说我们的prepare()方法必须先Loop()方法使用。这样才有looper对象。然后就是第6行,获取在Looper中的MessageQueue实例,然后第13行开始一个无限for循环,不断从MessageQueue里面获取Message,如果msg不存在的话,则return。如果msg存在的话,调用msg.target.dispatchMessgae()方法,去处理Message。
那msg的target是谁。不用想,肯定是Handler,但是Handler怎么就成了msg的target了呢,我们看一下Handler的代码。
  1. public Handler() {  
  2.         this(nullfalse);  
  3. }  
  4. public Handler(Callback callback, boolean async) {  
  5.         if (FIND_POTENTIAL_LEAKS) {  
  6.             final Class<? extends Handler> klass = getClass();  
  7.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  8.                     (klass.getModifiers() & Modifier.STATIC) == 0) {  
  9.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  10.                     klass.getCanonicalName());  
  11.             }  
  12.         }  
  13.   
  14.         mLooper = Looper.myLooper();  
  15.         if (mLooper == null) {  
  16.             throw new RuntimeException(  
  17.                 "Can't create handler inside thread that has not called Looper.prepare()");  
  18.         }  
  19.         mQueue = mLooper.mQueue;  
  20.         mCallback = callback;  
  21.         mAsynchronous = async;  
  22.     }  
 OK,第14行的时候,Handler获取了当前线程的Looper对象,然后从这个Looper对象中取到了对应的MessageQueue。这样Hadnler和Looper还有MessageQueue就勾搭上了。
但是还是没有看到msg.target是在哪儿设置的。但是我们知道我们用Handler经常用的一个方法是sendMessage(Message msg)。
我们来看看相关的源码:
[java] view plain copy
  1. public final boolean sendMessage(Message msg)  
  2.  {  
  3.      return sendMessageDelayed(msg, 0);  
  4.  }  
[java] view plain copy
  1. public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {  
  2.      Message msg = Message.obtain();  
  3.      msg.what = what;  
  4.      return sendMessageDelayed(msg, delayMillis);  
  5.  }  
[java] view plain copy
  1. public final boolean sendMessageDelayed(Message msg, long delayMillis)  
  2.    {  
  3.        if (delayMillis < 0) {  
  4.            delayMillis = 0;  
  5.        }  
  6.        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);  
  7.    }  
[java] view plain copy
  1. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {  
  2.        MessageQueue queue = mQueue;  
  3.        if (queue == null) {  
  4.            RuntimeException e = new RuntimeException(  
  5.                    this + " sendMessageAtTime() called with no mQueue");  
  6.            Log.w("Looper", e.getMessage(), e);  
  7.            return false;  
  8.        }  
  9.        return enqueueMessage(queue, msg, uptimeMillis);  
  10.    }  

原来sendMessage最后调用的是sendMessageAtTime方法,然后先获取到了咱们在构造函数中得到的MessageQueue。然后在调用enqueueMessage方法。

[java] view plain copy
  1. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {  
  2.        msg.target = this;  
  3.        if (mAsynchronous) {  
  4.            msg.setAsynchronous(true);  
  5.        }  
  6.        return queue.enqueueMessage(msg, uptimeMillis);  
  7.    }  
这里有了,第2行,msg.target=this. Message和它的target对象关联上了。然后下面就是调用MessageQueue的enqueueMessage方法把消息放入MessageQueue。
回过头,我们其实还在msg.target.dispatchMessage这个地方。
那dispatchMessage方法在干嘛呢??
  1. public void dispatchMessage(Message msg) {  
  2.         if (msg.callback != null) {  
  3.             handleCallback(msg);  
  4.         } else {  
  5.             if (mCallback != null) {  
  6.                 if (mCallback.handleMessage(msg)) {  
  7.                     return;  
  8.                 }  
  9.             }  
  10.             handleMessage(msg);  
  11.         }  
  12.     }  
ok,很清楚。如果对应的msg有callBack,那么就用 handleCallback(msg); 这个方法,如果没有,那么看看Handler自己的CallBack存在不存在,存在的话,则调用Callback.handleMessage(msg)方法,如果也不存在电话,最后调用自己的handleMessage方法。那handleMessage方法源码里面做了啥?

  1. public void handleMessage(Message msg) {  
  2.   }  
Nothing。什么都没有做。所以我们自己要去实现这个方法。
当然如果你Handler有了CallBack,且CallBack的handleMessage返回true的话,那么久不会在调用handler本身的handleMessage方法了。
总结一下:
Looper通过prepare方法生成一个在当前线程的Looper和这个Looper的MessageQueue。
Looper通过loop()方法无限循地从Message里面获取msg。然后交给msg的target去dispatchMessage。
Handler的构造方法把Handler与当前线程中的Looper以及它的MessageQueue关联起来。通过sendMessage等方法,把msg与Handler绑定起来,然后通过MessageQueue的enqueue方法把message加入到消息队列中。因为消息队列中的消息是不断取出的,然后就调用了Handler的dispatch方法去处理message。那最终可以是handleCallback(msg);这个方法去处理消息,或者Handler的CallBack去处理。或者通过Handler本身的handleMessage去处理消息。
学习的东西,写出来最重要了。

原创粉丝点击