Handler,Message,Looper的那一点事儿

xiaoxiao2021-02-28  141

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

Looper中维护一个MessageQueue。

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

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

Looper的prepare的代码

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

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

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

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

public static void loop() {           final Looper me = myLooper();           if (me == null) {               throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");           }           final MessageQueue queue = me.mQueue;              // 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.recycle();           }   }   上面的第二行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的代码。 public Handler() {           this(nullfalse);   }   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;       }    OK,第14行的时候,Handler获取了当前线程的Looper对象,然后从这个Looper对象中取到了对应的MessageQueue。这样Hadnler和Looper还有MessageQueue就勾搭上了。 但是还是没有看到msg.target是在哪儿设置的。但是我们知道我们用Handler经常用的一个方法是sendMessage(Message msg)。 我们来看看相关的源码: [java]  view plain  copy public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }   [java]  view plain  copy public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageDelayed(msg, delayMillis);    }   [java]  view plain  copy public final boolean sendMessageDelayed(Message msg, long delayMillis)      {          if (delayMillis < 0) {              delayMillis = 0;          }          return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);      }   [java]  view plain  copy 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);      }  

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

[java]  view plain  copy private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {          msg.target = this;          if (mAsynchronous) {              msg.setAsynchronous(true);          }          return queue.enqueueMessage(msg, uptimeMillis);      }   这里有了,第2行,msg.target=this. Message和它的target对象关联上了。然后下面就是调用MessageQueue的enqueueMessage方法把消息放入MessageQueue。 回过头,我们其实还在msg.target.dispatchMessage这个地方。 那dispatchMessage方法在干嘛呢?? public void dispatchMessage(Message msg) {           if (msg.callback != null) {               handleCallback(msg);           } else {               if (mCallback != null) {                   if (mCallback.handleMessage(msg)) {                       return;                   }               }               handleMessage(msg);           }       }   ok,很清楚。如果对应的msg有callBack,那么就用  handleCallback(msg); 这个方法,如果没有,那么看看Handler自己的CallBack存在不存在,存在的话,则调用Callback.handleMessage(msg)方法,如果也不存在电话,最后调用自己的handleMessage方法。那handleMessage方法源码里面做了啥? public void handleMessage(Message msg) {     }   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去处理消息。 学习的东西,写出来最重要了。

转载请注明原文地址: https://www.6miu.com/read-19830.html

最新回复(0)