Android 中Handler Message MessageQueue looper 关系及流程

来源:互联网 发布:淘宝客服平均工资 编辑:程序博客网 时间:2024/05/23 23:10

根据本人对源码的查看   


Hanlder中有  MessageQueue  Looper  其中 MessageQueue是从looper中获取的   


Looper 类中 封装了一个MessageQueue对象   而  MessageQueue中存放Message对象  


简单的说流程就是 

先创建一个handler对象  这个对象构造函数会调用Looper.mylooper()方法 来获取一个和线程绑定的looper  

创建一个Message对象  放入内容   然后通过handler的sendMessage方法 发送到Hanlder中   然后放入MessageQueue中  

之后线程调用 looper.loop()方法  就可以轮询队列取出消息   执行消息的dispatchMessage方法   调用  handleMessage方法  执行相应操作

其中在子线程中 声明Handler对象会 出现异常   因为looper.mylooper()这个方法  获取looper对象  可是这个对象是空的 必须执行 looper.prepare()方法 设置一个looper对象  但这个方法不可重复调用    而在主线程中 会自动开启这个方法  所以不需要 

因此在子线程中定义handler  需要先prepare一下  然后 创建handler  然后调用loop方法  


接下来看 源代码:

1. 首先定义handler 调用Looper.prepare()方法 向ThreadLocal对象中设置一个该线程的Looper对象  

    然后调用构造函数 

 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(); //此处调用myLooper方法关联looper 这个方法会根据当前线程来获得与线程相关的looper对象  使用前必须先prepare          if (mLooper == null) {            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;  //获取looper中的队列        mCallback = callback;   //如果有callback接口传递  赋值        mAsynchronous = async;     }
其中也有重载的构造函数 可以直接传递looper进来   那样就不需要调用mylooper方法了  

总的来说  这个构造函数的作用就是获取looper对象  并通过looper对象给handler中的一些变量赋值(比如mQueue等)

2.在另一个线程中sendMessage(msg) 方法  Message可通过obtain方法  获取

public static Message obtain() {        synchronized (sPoolSync) {            if (sPool != null) {                Message m = sPool;                sPool = m.next;                m.next = null;                sPoolSize--;                return m;            }        }        return new Message();    }
此方法会从Message池中取出一个消息使用  如果没有 才创建一个消息  这样效率比直接new高 

sendMessage方法:

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);    }
这个方法很简单  就是向 mQueue队列中放入消息即可  

3.由于创建handler对象之后调用了loop方法   loop方法会轮询队列 取出Message对象 然后执行handler的dispatchMessage函数  这里有一点要说明  Message在发送的时候会与handler绑定   Message中内置一个target对象  这个对象存放的就是handler对象  所以可以调用 handler的dispatchMessage方法  

 public static void loop() {       <span style="white-space:pre"></span>........省略        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);  //这句是重点   调用  handler的dispatchMessage方法             ......省略            msg.recycle();        }    }

4.由于在handler 创建时 会重写他的handleMessage方法  而dispatchMessage中 会调用这个方法  所以就实现了线程间通信  

 public void dispatchMessage(Message msg) {        if (msg.callback != null) {  //这里如果message有callback  直接执行  不执行handler的方法            handleCallback(msg);        } else {            if (mCallback != null) {   //如果在声明handler时的构造函数中传入了 callback对象  那么先执行之歌回调  这个会掉的主要作用是在处理消息之前完成一些事情                if (mCallback.handleMessage(msg)) {  //这里调用  handler方法的重写方法   实现线程间通信                    return;                }            }            handleMessage(msg);        }    }

总结:  个人理解   为了在线程间通信  引用了handler对象   其实也不是很复杂   也就是创建了一个类  可以在2个线程之间传递数据罢了  中间解决了一些线程之间的问题 

一个线程发送  另一个线程 轮询取出执行   如有理解错误  希望可以被指出修改 




0 0