Handler,MessageQueue,Message,Looper源码分析

Handler机制源码分析

我的github博客详解


Handler 核心成员变量与方法:


MessageQueue,Message 核心成员变量与方法:


Looper 核心成员变量与方法:


Handler的工作原理涉及:Handler,MessageQueue,Message,Looper,ThreadLocal 等多个类


简单分析:

1,Handler初始化都做些什么?

2,Handler的常用几种方法有哪些?

3,Handler把Meesage发送到什么地方去了?

4,MessageQueue是什么,他与Handler,Message,Looper存在什么样的关系?

5,Message源码分析

6,Handler,Message,MessageQueue,Looper之间是怎么样工作的?

7,子线程也能使用Handler,MessageQueue,Looper机制吗?


开始分析:


1,Handler初始化都做些什么?


先看看Handler的构造函数



        public Handler() {
            this(null, false);
        }



        public Handler(Looper looper) {
            this(looper, null, false);
        }



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



        public Handler(Looper looper, Callback callback, boolean async) {
            mLooper = looper;
            mQueue = looper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }



从上面可以看出,Handler有多个构造器。从代码最多的构造器看到,Handler初始化做了三件事:

1-1,获取到当前线程的Looper


        mLooper = Looper.myLooper();


        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }

1-2,获取当前Looper的消息队列MessageQueue


        mQueue = mLooper.mQueue;

1-3,初始化callback


         mCallback = callback;



2,Handler的常用几种方法有哪些?




        public final Message obtainMessage()
        {
            return Message.obtain(this);
        }

        public final boolean postDelayed(Runnable r, long delayMillis)
        {
            return sendMessageDelayed(getPostMessage(r), delayMillis);
        }

            public final void removeCallbacks(Runnable r)
        {
            mQueue.removeMessages(this, r, null);
        }

        public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }


3,Handler把Meesage发送到什么地方去了?


当Handler调用sendMessage方法时,Handler会把Message放入到Looper的MessageQueue中。

值得注意的是,sendMessage时,Handler把自己对象引用也给Message,在Message成员变量target里


        public final boolean sendMessage(Message msg)
        {
            return sendMessageDelayed(msg, 0);
        }


        public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
        }


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

        private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }



4,MessageQueue是什么,他与Handler,Message,Looper存在什么样的关系?


MessageQueue拥有Message作为成员变量,而Message类中存在Message next成员变量与静态的Meesage sPools变量,

这就意味着Message类中存在自己的对象,自己当中包含自己,形成了一条链表结构,不亚于数组的结构。

Handler把Message交给MessageQueue之后,MessageQueue把这个Message对象引用下来



        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(TAG, 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;

可以看到最后一行,mMessages成员变量拿到了传递进来的message引用

而Looper存在一个成员变量就是MessageQueue,在Looper的loop方法中,从MessageQueue找出已存在的Message



        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
                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.traceBegin(traceTag, msg.target.getTraceName(msg));
                }
                try {
                    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();
            }
        }

看到for循环里的第一行,从MessageQueue取出Message了

接下来看Looper怎么处理Message的?

看着一行代码:


        msg.target.dispatchMessage(msg);

上面我们知道message的target就是Handler,绕了一圈,还是让Handler来处理这个Message,进入方法中:



        /**
         * 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);
            }
        }




        private static void handleCallback(Message message) {
            message.callback.run();
        }

        public interface Callback {
            public boolean handleMessage(Message msg);
        }

        public void handleMessage(Message msg) {
        }

可以看到,首先判断message有没有callback,这个callback就是平时我们调用Handler.post(run)传递一个Runable对象回调的方法。

而mCallback是Handler内部的一个接口,也可以使用这个接口。最后才是回调handleMessage这个方法


最后,Message被回收:



        msg.recycleUnchecked();

        void recycleUnchecked() {
            // Mark the message as in use while it remains in the recycled object pool.
            // Clear out all other details.
            flags = FLAG_IN_USE;
            what = 0;
            arg1 = 0;
            arg2 = 0;
            obj = null;
            replyTo = null;
            sendingUid = -1;
            when = 0;
            target = null;
            callback = null;
            data = null;

            synchronized (sPoolSync) {
                if (sPoolSize < MAX_POOL_SIZE) {
                    next = sPool;
                    sPool = this;
                    sPoolSize++;
                }
            }
        }


5,Message源码分析


跟着Handler,sendMessage绕了一圈,路过MessageQueue,Looper,最后还是让Handler来处理这个Message。

那好,现在我们来研究一下这个Message



public final class Message implements Parcelable {

    public int what;

    public int arg1; 

    public int arg2;

    public Object obj;


    /*package*/ int flags;

    /*package*/ long when;

    /*package*/ Bundle data;

    /*package*/ Handler target;

    /*package*/ Runnable callback;

    // sometimes we store linked lists of these things
    /*package*/ Message next;

    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 50;

先看Message源码中的成员变量:

what,arg1,arg2,这些是用来区分Message来使用的,一般只用what,这里告诉你:这三个都可以随便用

long when 是message执行的时间

Handler target 这是就是引用的Handler了,每一个Message都知道自己是被哪一个Handler来处理的

Runnbale callback 这就是post传递进去的Runnable对象,也被Message拿到了,

所以说,sendMessage和post最终都是以Message的形式来处理的

Message next 这是Message里包含下一个Message,形成了单链表结构

static Message sPool 这就是传说中的消息池了,没错他就是一个Message对象而已,静态的成员变量。

static final int MAX_POOL_SIZE = 50; google工程师限时这个消息池的最大长度,50个


接来看我们来研究Message如何创建和被回收的。

首先,创建Message:


        public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {
                    Message m = sPool;
                    sPool = m.next;
                    m.next = null;
                    m.flags = 0; // clear in-use flag
                    sPoolSize--;
                    return m;
                }
            }
            return new Message();
        }



可以看出,如过消息池为空,直接new出来。否则直接去池里取一个Message对象,把下一个Message设置到池里,池数目减减

如果谁以后创建Message还自己手动New的话,我在这先鄙视一下…

当使用完毕之后,Message会被回收



        void recycleUnchecked() {
            // Mark the message as in use while it remains in the recycled object pool.
            // Clear out all other details.
            flags = FLAG_IN_USE;
            what = 0;
            arg1 = 0;
            arg2 = 0;
            obj = null;
            replyTo = null;
            sendingUid = -1;
            when = 0;
            target = null;
            callback = null;
            data = null;

            synchronized (sPoolSync) {
                if (sPoolSize < MAX_POOL_SIZE) {
                    next = sPool;
                    sPool = this;
                    sPoolSize++;
                }
            }
        }



这里把Message的成员变量清空个遍,sPool = this ,这行就是把Message还回池中了,池数目加加


6,Handler,Message,MessageQueue,Looper之间是怎么样工作的?


1,创建Handler,Handler获取到当前线程的Looper,Looper里的MessageQueue

2,创建Message,是通过池是否有消息来返回Message的,池一个都没有才会new

3,sendMessage与post,本质都是Message,最后获取Handler引用,Message被传递给了MessageQueue

4,Looper的loop方法,检查Looper的MesaageQueue是否有Message,有的话把Message传递给Handler来处理

5,Message回收


7,子线程也能使用Handler,MessageQueue,Looper机制吗?


去看Looper源码头上的注释就知道了:




        /**
          * Class used to run a message loop for a thread.  Threads by default do
          * not have a message loop associated with them; to create one, call
          * {@link #prepare} in the thread that is to run the loop, and then
          * {@link #loop} to have it process messages until the loop is stopped.
          *
          * <p>Most interaction with a message loop is through the
          * {@link Handler} class.
          *
          * <p>This is a typical example of the implementation of a Looper thread,
          * using the separation of {@link #prepare} and {@link #loop} to create an
          * initial Handler to communicate with the Looper.
          *
          * <pre>
          *  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();
          *      }
          *  }</pre>
          */
        public final class Looper {



google工程师都把代码写给你了。闲麻烦的话,那就去用google工程师又帮你写好的HandlerThread这个类吧,

子线程使用Handler,Looper机制。

什么时候用子线程开启Handler,Looper机制呢,看需求吧。Handler机制拥有Message 50个消息队列,

能很好的保证处理的任务或者消息以线性的方式来执行,在子线程保证线性执行噢。

但是不能玩太耗时的操作,毕竟是队列。

分析就到这里了


11/8/2016 4:29:08 PM

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值