Handle的原理代碼實現

 

  本文從源碼的角度來分析Handle如何實現的。async

 

  首先咱們得知道Handler,Looper,Message Queue三者之間的關係ide

  - Handler封裝了消息的發送,也負責接收消。內部會跟Looper關聯。函數

  - Looper 消息封裝的載,內部包含了MessageQueue,負責從MessageQueue取出消息,而後交給Handler處理oop

  - MessageQueue 就是一個消息隊列,負責存儲消息,有消息過來就存儲起來,Looper會循環的從MessageQueue讀取消息。(西安尚學堂)軟件開發源碼分析

 

  源碼分析post

  當咱們new一個Handler對象的時候,看看他的構造方法裏面作了什麼.ui

  

public Handler(Callback callback, boolean async) {

  if (FIND_POTENTIAL_LEAKS) {

  final Class 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對象。this

 

  Looper myLooper()spa

  跟進去看看Looper.myLooper()方法作了什麼。這是一個靜態方法,能夠類名.方法名直接調用。線程

  

public static @Nullable Looper myLooper() {

  return sThreadLocal.get();

  }

 

  這個方法裏面就一行代碼,從sThreadLocal中獲取一個Looper對象,sThreadLocal是一個ThreadLocal對象,能夠在一個線程中存儲變量。底層是ThreadLocalMap,既然是Map類型那確定得先set一個Looper對象,而後咱們才能從sThreadLocal對象裏面get一個Looper對象。

 

  ActivityThread main()

  ActivityThread類是Android APP進程的初始類,它的main函數是這個APP進程的入口。那麼這個main函數幹了什麼事呢。

  

public static final void main(String[] args) {

  ------

  Looper.prepareMainLooper();

  if (sMainThreadHandler == null) {

  sMainThreadHandler = new Handler();

  }

  ActivityThread thread = new ActivityThread();

  thread.attach(false);

  if (false) {

  Looper.myLooper().setMessageLogging(new

  LogPrinter(Log.DEBUG, "ActivityThread"));

  }

  Looper.loop();

  -----

  }

 

  在第二行代碼調用Looper.prepareMainLooper()方法,第13行調用了Looper.loop()方法。

 

  Looper prepareMainLooper()

  繼續跟進Looper.prepareMainLooper()方法,在這個方法中第一行代碼調用了內部的prepare方法。prepareMainLooper有點像單例模式中的getInstance方法,只不過getInstance會當時返回一個對象,而prepareMainLooper會新建一個Looper對象,存儲在sThreadLocal中。

  

public static void prepareMainLooper() {

  prepare(false);

  synchronized (Looper.class) {

  if (sMainLooper != null) {

  throw new IllegalStateException("The main Looper has already been prepared.");

  }

  sMainLooper = myLooper();

  }

  }

 

  Looper prepare()

  繼續跟進prepare方法,看第5行代碼,新建了一個Looper對象,調用sThreadLocal.set方法把Looper對象保存起來。

  

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

  }

 

  Looper 構造方法

  Looper內部包含了MessageQueue,其實就是在new Looper對象的時候就new了一個MessageQueue對象。

 

 private Looper(boolean quitAllowed) {

  mQueue = new MessageQueue(quitAllowed);

  mThread = Thread.currentThread();

  }

 

  Looper loop()

  ActivityThread類main方法中調用了Looper的兩個方法,前面咱們解釋了prepareMainLooper(),如今來看第二個方法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;//從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) {

  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 long traceTag = me.mTraceTag;

  if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {

  Trace.traceBegin(traceTag, msg.target.getTraceName(msg));

  }

  try {

  //調用handler的dispatchMessage方法,把消息交給handler處理

  msg.target.dispatchMessage(msg);

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

  }

  }

 

  這個方法的代碼比較多。其實就是一個死循環,一直會從MessageQueue中取消息,若是取到了消息就會執行msg.target.dispatchMessage(msg)這行代碼,msg.target就是handler,其實就是調用handler的dispatchMessage方法,而後把從MessageQueue中取到的message傳入進去。

 

  Handler dispatchMessage()

  

public void dispatchMessage(Message msg) {

  //若是callback不爲空,說明發送消息的時候是post一個Runnable對象

  if (msg.callback != null) {

  handleCallback(msg);

  } else {

  if (mCallback != null) {//這個是用來攔截消息的

  if (mCallback.handleMessage(msg)) {

  return;

  }

  }

  handleMessage(msg);//最終調用咱們重寫的handleMessage方法

  }

  }

 

  這個方法對消息作最後處理,若是是post類型調用handleCallback方法處理,若是是sendMessage發送的消息。看咱們有沒有攔截消息,若是沒有最終調用handleMessage方法處理。

 

  Handler handleCallback()

  看到這裏咱們知道爲何post一個Runnable對象,run方法執行的代碼在主線程了吧,由於底層根本就沒有開啓線程,就只是調用了run方法而已。

  

private static void handleCallback(Message message) {

  message.callback.run();

  }

 

  前面咱們從建立handler對象開始,以及建立Looper,建立MessageQueue的整個流程,如今來分析下,當咱們調用post以及sendMessage方法時,怎麼把Message添加到MessageQueue?

 

  Handler post()

  調用了getPostMessage方法,把Runnable傳遞進去。

  

public final boolean post(Runnable r)

  {

  return sendMessageDelayed(getPostMessage(r), 0);

  }

  Handler getPostMessage()

 

  首先調用Message.obtain()方法,取出一個Message對象,這個方法以前有講過,而後把Runnable對象賦值了Message對象的callback屬性。看到這裏咱們也明白了dispatchMessage方法爲何要先判斷callback是否爲空了吧。

  

private static Message getPostMessage(Runnable r) {

  Message m = Message.obtain();

  m.callback = r;

  return m;

  }

 

  Handler enqueueMessage()

  在post方法裏面調用了sendMessageDelayed方法,其實最終調用的是enqueueMessage方法,因此我這裏就直接看enqueueMessage方法源碼。第一行代碼就把handler本身賦值給messgae對象的target屬性。而後調用MessageQueue的enqueueMessage方法把當前的Messgae添加進去。

  

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

  msg.target = this;

  if (mAsynchronous) {

  msg.setAsynchronous(true);

  }

  return queue.enqueueMessage(msg, uptimeMillis);

  }

 

  小結

  總結:handler負責發送消息,Looper負責接收Handler發送的消息,並直接把消息回傳給Handler本身。MessageQueue就是一個存儲消息的容器。

相關文章
相關標籤/搜索