根据本人对源码的查看
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); } }
一个线程发送 另一个线程 轮询取出执行 如有理解错误 希望可以被指出修改