美文网首页
Android系统Java源码探索(4)—Handler消息机制

Android系统Java源码探索(4)—Handler消息机制

作者: IIGEOywq | 来源:发表于2018-01-25 12:14 被阅读50次

一 前言

对于开发者来说,Android的消息机制离不开Handler,下面我们看看官网对Handler的解释:

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

上面这段话,说的比较简单,意思大概就是Handler用来向一个线程的消息队列中发送和处理消息的。而且每一个Handler实例都和一个线程/消息队列相关联。当开发者在一个线程创建一个Handler时,该Handler就会被绑定到该线程及该线程创建的消息队列(消息队列通过线程的Looper创建),然后发送和读取消息。
Android的消息机制源码实现主要包括四个概念:

  • Looper——用来创建消息队列;
  • MessageQueue——发送和读取消息;
  • Handler——对于开发者而言,封装了MessageQueue的发送和读取消息;
  • Message——消息格式;

二 Handler消息机制的相关源码

主要分析Looper,Handler两个类。

2.1 Looper

先看looper类中的注释,说明了Handler的使用方法。

class LooperThread extends Thread {
       public Handler mHandler;
       public void run() {
           //1
           Looper.prepare();
           //2
            mHandler = new Handler() {
               public void handleMessage(Message msg) {
                  // 
                }
           };
          //
           Looper.loop();
        }
public final class Looper {
   
    private static final String TAG = "Looper";
   //ThreadLocal--线程本地存储,是用来存储线程的数据,但针对一个线程而言,只会读取自己线程的数据。
ThreadLocal<Looper>用来存储自己线程的Looper。
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class
    final MessageQueue mQueue;
    final Thread mThread;
    private Printer mLogging;
    private long mTraceTag;
    private long mSlowDispatchThresholdMs;
   // a.非UI线程初始化Looper
    public static void prepare() {
        prepare(true);
    }
    private static void prepare(boolean quitAllowed) {
        //quitAllowed表示允许退出,默认是true
        if (sThreadLocal.get() != null) {
           //对于一个线程,在Looper未初始化之前,如果ThreadLocal获取的数据不为空,会抛出异常,因为一个线程只对应一个Looper
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //初始化Looper,并将Looper存储下来。
        sThreadLocal.set(new Looper(quitAllowed));
    }
 // b.UI线程初始化Looper
 // 对于Activity线程(UI线程)比较特殊,他会在创建时,就会创建一个Looper,无需再使用perpare创建。
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    /**
     * Returns the application's main looper, which lives in the main thread of the application.
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }
  //Looper开启循环,读取队列中
  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 (;;) {
            //读取MessageQueue的下一条消息
            Message msg = queue.next(); // 可能阻塞
            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 slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
                //分发Message
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (slowDispatchThresholdMs > 0) {
                final long time = end - start;
                if (time > slowDispatchThresholdMs) {
                    Slog.w(TAG, "Dispatch took " + time + "ms on "
                            + Thread.currentThread().getName() + ", h=" +
                            msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                }
            }
            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();
        }
    }
   //从ThreadLocal获取已经存储的Looper对象
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
    /**
     * Return the {@link MessageQueue} object associated with the current
     * thread.  This must be called from a thread running a Looper, or a
     * NullPointerException will be thrown.
     */
    public static @NonNull MessageQueue myQueue() {
        return myLooper().mQueue;
    }
   //初始化Looper
    private Looper(boolean quitAllowed) {
       //创建消息队列
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
    /**
     * Returns true if the current thread is this looper's thread.
     */
    public boolean isCurrentThread() {
        return Thread.currentThread() == mThread;
    }

    public void setMessageLogging(@Nullable Printer printer) {
        mLogging = printer;
    }
    /** {@hide} */
    public void setTraceTag(long traceTag) {
        mTraceTag = traceTag;
    }
    /** {@hide} */
    public void setSlowDispatchThresholdMs(long slowDispatchThresholdMs) {
        mSlowDispatchThresholdMs = slowDispatchThresholdMs;
    }
   
    public void quit() {
        mQueue.quit(false);
    }
   
    public void quitSafely() {
        mQueue.quit(true);
    }
    /**
     * Gets the Thread associated with this Looper.
     *
     * @return The looper's thread.
     */
    public @NonNull Thread getThread() {
        return mThread;
    }

    public @NonNull MessageQueue getQueue() {
        return mQueue;
    }
   ...... 
}

2.2 Handler

public class Handler {
    
    private static final boolean FIND_POTENTIAL_LEAKS = false;
    private static final String TAG = "Handler";
    private static Handler MAIN_THREAD_HANDLER = null;
   
    public interface Callback {
        public boolean handleMessage(Message msg);
    }
    
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }
    
    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
    // d1. 创建Handler对象
    public Handler() {
        this(null, false);
    }
   
    public Handler(Callback callback) {
        this(callback, false);
    }
   
    public Handler(Looper looper) {
        this(looper, null, false);
    }
    
    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
   
    public Handler(boolean async) {
        this(null, async);
    }

    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());
            }
        }
       //d2.由于已经执行了Looper.prepare(),所以从ThreadLocal获取Looper对象;
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        //d3.获取Looper类初始化时,创建的MessageQueue对象
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
   
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    /** @hide */
    @NonNull
    public static Handler getMain() {
        if (MAIN_THREAD_HANDLER == null) {
            MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
        }
        return MAIN_THREAD_HANDLER;
    }
    /** @hide */
    @NonNull
    public static Handler mainIfNull(@Nullable Handler handler) {
        return handler == null ? getMain() : handler;
    }
    /** {@hide} */
    public String getTraceName(Message message) {
        final StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName()).append(": ");
        if (message.callback != null) {
            sb.append(message.callback.getClass().getName());
        } else {
            sb.append("#").append(message.what);
        }
        return sb.toString();
    }
   
    public String getMessageName(Message message) {
        if (message.callback != null) {
            return message.callback.getClass().getName();
        }
        return "0x" + Integer.toHexString(message.what);
    }
   
    public final Message obtainMessage()
    {
        return Message.obtain(this);
    }
  
    public final Message obtainMessage(int what)
    {
        return Message.obtain(this, what);
    }
    
   
    public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }
 
    public final Message obtainMessage(int what, int arg1, int arg2)
    {
        return Message.obtain(this, what, arg1, arg2);
    }
    

    public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
    {
        return Message.obtain(this, what, arg1, arg2, obj);
    }
   
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    
  
    public final boolean postAtTime(Runnable r, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }
    
   
    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }
    
    public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
    
  
    public final boolean postAtFrontOfQueue(Runnable r)
    {
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }
 
    public final boolean runWithScissors(final Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }
    /**
     * Remove any pending posts of Runnable r that are in the message queue.
     */
    public final void removeCallbacks(Runnable r)
    {
        mQueue.removeMessages(this, r, null);
    }
    /**
     * Remove any pending posts of Runnable <var>r</var> with Object
     * <var>token</var> that are in the message queue.  If <var>token</var> is null,
     * all callbacks will be removed.
     */
    public final void removeCallbacks(Runnable r, Object token)
    {
        mQueue.removeMessages(this, r, token);
    }
   
   //e1.handler发送消息
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
    
    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
   
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
   
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }
   //e2.延迟发送消息
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
   //e3.定时发送消息
    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);
    }
   
    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        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, 0);
    }
   //e4.真正发送消息的方法
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
       //把当前Handler复制给Message的taget属性
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

    public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);
    }

    public final void removeMessages(int what, Object object) {
        mQueue.removeMessages(this, what, object);
    }
   
    public final void removeCallbacksAndMessages(Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }
    /**
     * Check if there are any pending posts of messages with code 'what' in
     * the message queue.
     */
    public final boolean hasMessages(int what) {
        return mQueue.hasMessages(this, what, null);
    }
    /**
     * Return whether there are any messages or callbacks currently scheduled on this handler.
     * @hide
     */
    public final boolean hasMessagesOrCallbacks() {
        return mQueue.hasMessages(this);
    }
   
    public final boolean hasCallbacks(Runnable r) {
        return mQueue.hasMessages(this, r, null);
    }

    public final Looper getLooper() {
        return mLooper;
    }
 
    private static Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }
    private static void handleCallback(Message message) {
        message.callback.run();
    }
   .......
}

三 Handler源码分析总结

根据源码画一张两个非UI线程之间Handler通信流程图,如下图:


非UI线程之间Handler流程.jpg

主要下面几个步骤:
*创建一个消息队列: 启动一个非UI线程(下面叫线程1),在线程里面调用Looper.prepare方法,创建一个Looper对象,每一个线程都会对应一个自己的Looper对象,同时Looper对象内部会创建一个消息队列;

  • 关联Handler与消息队里:在线程1中创建实例化一个Handler对象,该Hander内部会从ThreadLocal获取上一步创建的Looper对象和MessageQueue对象,这样Handler就和消息队列关联起来了;
  • 创建一个Message对象:接着启动一个新的子线程(叫线程2),在线程2中首先创建一个Message对象,注意这是的Message的target还是空的;
  • 发送消息:继续在线程2中调用handler.sendMessage方法发送消息,该方法内部最终调用了MessageQueue(这个messagequeue对象就是之前Looper创建,并在实例化Handler时,传给了handler)的enqueueMessage方法;
  • 读取消息:在线程1中调用Looper.loop循环读取线程2中发送到消息队列的数据;
  • 分发消息:调用handler的dispathcMessage分发消息给对应的handler;
  • 处理消息:Handler处理消息;

Android提供了个HandlerThread类就是一个结合了Handler的非UI线程
源码如下:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    ......
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }
    @Override
    public void run() {
        mTid = Process.myTid();
       //1
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        //2
        Looper.loop();
        mTid = -1;
    }
   ....
}

上面源码的流程,和我们之前说的非UI线程创建消息队列的逻辑一模一样,就不在说了。

注意,在ActivityTherad线程启动时,会自动执行Looper.prepare()和Looper.loop()方法,所以开发者不需要在执行这两个方法。

由于本人能力有限,有的方面理解不当,后续会根据情况继续调整。

相关文章

网友评论

      本文标题:Android系统Java源码探索(4)—Handler消息机制

      本文链接:https://www.haomeiwen.com/subject/abnyaxtx.html