• android 线程消息深入


        在网上有许多资料对这三者关系的分析,但都比较笼统不够细致入微.

    以下是自己深入源码分析其结果.

    Handler 源码:

    public class Handler {

        private static final boolean FIND_POTENTIAL_LEAKS = false;

        private static final String TAG = "Handler";

     

        public interface Callback {

            public boolean handleMessage(Message msg);

        }

        final MessageQueue mQueue;

        final Looper mLooper;

        final Callback mCallback;

        IMessenger mMessenger;

        /**

         * Subclasses must implement this to receive messages.

         */

        public void handleMessage(Message msg) {

        }

        public Handler() {

            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 = null;

        }

     

        /**

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

            }

        }

        public Handler() {

            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 = null;

    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis)

        {

            boolean sent = false;

            MessageQueue queue = mQueue;

            if (queue != null) {

                msg.target = this;

                sent = queue.enqueueMessage(msg, uptimeMillis);

            }

            else {

                RuntimeException e = new RuntimeException(

                    this + " sendMessageAtTime() called with no mQueue");

                Log.w("Looper", e.getMessage(), e);

            }

            return sent;

        }

     

    从源码分析可以看出:

    handler在无参数的构造方法中调用Looper.myLooper()方法,里面就是从当前线程里面获取一个Looper对象,如果没有则创建.这样对Looper就进行初始化,初始化Looper的同时一并初始化MessageQueue,并且从中得到looper的MessageQueue .可以看出Handler就是Looper和MessageQueue的管理者和调度者.

    其中最重要的是:sendMessageAtTime(Message msg, long uptimeMillis)这个方法,当你往Handler中发送Message消息的时候,从代码看出他自己并不去处理Message ,而是交给了MessageQueue.由以下从这段代码来处理:

    queue.enqueueMessage(msg, uptimeMillis), 其具体实现要看下面的对

    MessageQueue的分析

     

     

    Looper结构关联的内容:

    Looper 源码:

    public class Looper {

        private static final boolean DEBUG = false;

        private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;

     

        // sThreadLocal.get() will return null unless you've called prepare().

        private static final ThreadLocal sThreadLocal = new ThreadLocal();

     

        final MessageQueue mQueue;

        volatile boolean mRun;

        Thread mThread;

        private Printer mLogging = null;

        private static Looper mMainLooper = null;

       

        public static final void prepare() {

            if (sThreadLocal.get() != null) {

                throw new RuntimeException("Only one Looper may be created per thread");

            }

            sThreadLocal.set(new Looper());

    }

    public static final void loop() {

            Looper me = myLooper();

            MessageQueue queue = me.mQueue;

            while (true) {

                Message msg = queue.next(); // might block

                if (msg != null) {

                    if (msg.target == null) {

                        return;

                    }

                    if (me.mLogging!= null) me.mLogging.println(

                            ">>>>> Dispatching to " + msg.target + " "

                            + msg.callback + ": " + msg.what

                            );

                    msg.target.dispatchMessage(msg);

                    if (me.mLogging!= null) me.mLogging.println(

                            "<<<<< Finished to    " + msg.target + " "

                            + msg.callback);

                    msg.recycle();

                }

            }

        }

    从源码可以看出Looper 封装的信息:

     

    Looper实质上是对当前线程, ThreadLocal,MessageQueue的封装,也就是负责在多线程之间传递消息的一个循环器.

     

    当你往Handler中添加消息的时候则,里面这个方法: public static final void loop()死循环的方法就会被系统调用,之后的功能代码是:

    msg.target.dispatchMessage(msg),则从MessageQueue中得到一个

    Message(msg),之后调用Handler的dispatchMessage(msg),这个方法内部实际调用的就是 Handler.handleMessage(msg)方法,这个就是我们在

    activity要重写的方法,所以我们就能够得到其他子线程传递的Message了.

     

    Message的源码分析:

    public final class Message implements Parcelable {

        public int what;

        public int arg1;

        public int arg2;

        public Object obj;

        public Messenger replyTo;

        long when;

        Bundle data;

        Handler target;    

        Runnable callback;

        Message next;

        private static Object mPoolSync = new Object();

        private static Message mPool;

        private static int mPoolSize = 0;

        private static final int MAX_POOL_SIZE = 10;

       

    When: 向Handler发送Message生成的时间

    Data: 在Bundler 对象上绑定要线程中传递的数据

    Next: 当前Message 对一下个Message 的引用

    Handler: 处理当前Message 的Handler对象.

    mPool: 通过字面理解可能叫他Message池,但是通过分析应该叫有下一个Message引用的Message链更加适合.

    其中Message.obtain(),通过源码分析就是获取断掉Message链关系的第一个Message.

    MessageQueue

     

    public class MessageQueue {

        Message mMessages;

        private final ArrayList mIdleHandlers = new ArrayList();

        private boolean mQuiting = false;

        boolean mQuitAllowed = true;

       

        public static interface IdleHandler {

            boolean queueIdle();

    }

     

    public final void addIdleHandler(IdleHandler handler) {

         if (handler == null) {

             throw new NullPointerException("Can't add a null IdleHandler");

         }

            synchronized (this) {

                mIdleHandlers.add(handler);

            }

    }

     

    final boolean enqueueMessage(Message msg, long when) {

            if (msg.when != 0) {

                throw new AndroidRuntimeException(msg

                        + " This message is already in use.");

            }

            if (msg.target == null && !mQuitAllowed) {

                throw new RuntimeException("Main thread not allowed to quit");

            }

            synchronized (this) {

                if (mQuiting) {

                    RuntimeException e = new RuntimeException(

                        msg.target + " sending message to a Handler on a dead thread");

                    Log.w("MessageQueue", e.getMessage(), e);

                    return false;

                } else if (msg.target == null) {

                    mQuiting = true;

                }

     

                msg.when = when;

                //Log.d("MessageQueue", "Enqueing: " + msg);

                Message p = mMessages;

                if (p == null || when == 0 || when < p.when) {

                    msg.next = p;

                    mMessages = msg;

                    this.notify();

                } else {

                    Message prev = null;

                    while (p != null && p.when <= when) {

                        prev = p;

                        p = p.next;

                    }

                    msg.next = prev.next;

                    prev.next = msg;

                    this.notify();

                }

            }

            return true;

        }

    mMessages: 为当前序列的第一个Message, 通过源码分析 MessageQueue并不是对许多Message 之间的关系维护,这样也许可以省去很多事把,而Message 之间的关系

    则统统丢给了Message自己去维护,这个可以从对Message源码分析可以理解.

     

    mIdleHandler: 保存的是一系列的handler的集合.

     

    其中final boolean enqueueMessage(Message msg, long when),

    这个方法就是上面提到Handler 处理消息时调用到的方法,对她理解了就显

    的很重要了,功能代码如下:

    msg.when = when;

    Message p = mMessages;

    if (p == null || when == 0 || when < p.when) {

           msg.next = p;

           mMessages = msg;

           this.notify();

    } else {

          Message prev = null;

          while (p != null && p.when <= when) {

                   prev = p;

                   p = p.next;

               }

           msg.next = prev.next;

           prev.next = msg;

           this.notify();

    }

     

    当向MessageQueue中添加消息的时候,判断当前的Message(mMessage)是否为空,

    如果为空或者when=0或者when<p.when: 则把要添加的Message(msg)赋给当

    前的Message(mMessage),并且将msg.next属性设为空,

    如果不为空: 则循环把当前的Message(mMessage)的下一个Message(next)进行遍历,用prev记住当前的message,直到找到prev的下一个Message为空的时候就退出循环,最后将msg接到prev的屁股后面,

    即这段代码: prev.next = msg;

  • 相关阅读:
    叉姐的魔法训练(第十课)---- 幽默大师卫冕战
    叉姐的魔法训练(第⑨课)---- 幽默大师职业赛
    叉姐的魔法训练(第八课)---- 幽默术
    叉姐的魔法训练(第七课)---- 在沙漠中的长途旅行
    叉姐的魔法训练(第六课)---- 暴雨术入门
    叉姐的魔法训练(第五课)---- 如何成为一名合格的小学生
    叉姐的魔法训练(第四课)---- 风系魔法的基本要领
    叉姐的魔法训练(第三课)---- 火球术入门
    叉姐的魔法训练(第二课)---- 冰系魔法入门
    叉姐的魔法训练(第一课)---- 初级魔法练习
  • 原文地址:https://www.cnblogs.com/622698abc/p/2739995.html
Copyright © 2020-2023  润新知