Handler原理浅析

Android线程相关这篇文章中说到了利用handler实现多线程并通信的方法,于是翻阅了很多博客,也查看了源码,终于从自己的角度理解了handler的原理。于是来梳理一下~

参考:

  1. Android异步消息处理机制完全解析,带你从源码的角度彻底理解
  2. Android异步处理三:Handler+Looper+MessageQueue深入详解

以线程A为主线程,B为新线程为例:

  1. A线程通过Looper.prepare()创建Looper对象,并初始化其MessageQueue消息队列,此时Looper与线程A绑定。
  2. A线程中new handler对象,构造函数中绑定Looper对象,同时也绑定了MessageQueue。
  3. 新建线程B,并执行操作,最后通过A线程中的handler调用sendMessage()方法或post()方法使Message入队Looper中的MessageQueue。
  4. A线程中的Looper对象通过调用Looper.loop()方法使MessageQueue中的Message不断出队,并分发到handler中。
  5. A线程中的handler的handleMessage方法处理回调。

从源码的角度:

  1. Looper.prepare(),即初始化Looper对象,及MessageQueue,同时绑定线程(ThreadLocal).

     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
     private static Looper sMainLooper;  // guarded by Looper.class
    
     final MessageQueue mQueue;
     final Thread mThread;
    
     public static void prepare() {
         prepare(true);
     }
    
     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));
     }
    
     private Looper(boolean quitAllowed) {
         mQueue = new MessageQueue(quitAllowed);
         mThread = Thread.currentThread();
     }
  2. Handler handler = new Handler(),新建hanlder对象,同时绑定Looper对象及MessageQueue。

     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;

    }

  3. 新建线程B,在其runnable的run方法中调用线程A的handler的sendMessage(Message)post(Runnable)方法,这两种方法最后都会调用handler中MessageQueue的enqueueMessage方法。该方法使Message按时间顺序排列。

`post(Runnable)`方法会新建带有Runnable对象的Message对象,然后在辗转调用`enqueueMessage`方法。

    public final boolean post(Runnable r)
    {
           return  sendMessageDelayed(getPostMessage(r), 0);
    }

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
  1. Looper.loop()通过死循环使MessageQueue中的Message出队直到队列为空,message.target即为handler的回调。

     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.recycleUnchecked();
         }
     }
  2. handler重写handleMessage方法处理回调,可以看到dispatchMessage方法即先判断有没有callback,而callback就是handler构造函数中的callback。

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

所以标准的线程通信写法为(可以从Looper的源码中看到):

class LooperThread extends Thread {
      public Handler mHandler;

  public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {
              // process incoming messages here
          }
      };

      Looper.loop();
  }

}