本系列笔记是我阅读Handler及相关类的源码时所记录的一些之前所不知道的知识点,该系列分为三部分,整体流程,Message对象回收原理,MessageQueue管理队列
Handler源码学习(一)流程
Handler源码学习(二)Message对象池
Handler源码学习(三)MessageQueue入队插队
1.创建handler — 默认构造方法会获取当前线程的looper,也可以传入指定的looper
* Default constructor associates this handler with the {@link Looper} for the * current thread. * * If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown. */ public Handler() { this(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; }
|
2.Looper
* This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
|
3.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); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
|
4.loop() — 取出消息
msg.target.dispatchMessage(msg);
|
5.dispatchMessage() — 分发消息
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); }
|
6.post — 各种post方法
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } 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); }
|
8.扩展
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
|
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } ViewRootImpl.getRunQueue().post(action); return true; }
|
7.收获
1.looper是通过 ThreadLoacal来保存 ,保证looper只被创建一次,且跟当前线程绑定,一个looper。
2.handler有多个构造方法,并不是必须要重写handleMessage方法,可以通过传入callback对象来处理消息,同时也可以给handler指定looper,因此handler可以给其它线程的looper发送消息。
3.MessageQueue不由handler创建,而是从looper中获取,一个looper对应有一个MessageQueue,因此一个looper必然可以对应多个handler,它们都是往这同一个消息队列中发送消息而已
4.Android中的主线程会调用Looper.prepareMainLooper() 方法来创建一个looper,因此不需要我们手动创建looper
5.handler发送延迟消息时,是通过但前时间+delayed时间,在某个时间去发送,因此如果在插入message时的时间是0,会容易导致排序问题
6.每一个Activity在创建的时候其实就已经创建了一个handler,runOnUiThread方法中使用的就是这个handler
7.view.post除了异步更新ui外还有一个作用,可以判断当前view是否已经attach window,在这个runnable任务被执行时,可以拿到尺寸等等,避免因为disattach造成异常