Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制。我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功能。Handler的内部实现主要涉及到如下几个类: Thread、MessageQueue和Looper。如下图:
Handler允许我们发送和处理Message , 还可以将Runnable对象关联到线程的MessageQueue;每个Handler实例都会与一个线程以及线程的消息队列相关联。当我们创建一个新的Handler后,这个Handler就会与它创建所在的线程和线程的消息队列绑定,它将Message 传送到消息队列,并执行从MessageQueue中出列的消息。如下图
下面是源码分析:
Handler
public Handler() { this(null, false); } public Handler(Callback callback) { this(callback, false); } public Handler(Looper looper) { this(looper, null, false); } public Handler(Looper looper, Callback callback) { this(looper, callback, false); } public Handler(boolean async) { this(null, async); } 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()); } } //Handler在此处关联当前线程的 Looper对象 mLooper = Looper.myLooper(); ... 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的构造里面这几个重载的构造里面都有一个boolean的参数,那么他是什么呢?官网解释是这个参数决定了是异步Handler将会被调用并且发送消息 ,并且执行了Looper.myLoop();
PS:Message.setAsynchronous(boolean)就是这个值,这里讲的构造是不传Looper参数的构造
继续往下看:
/** * 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); //如果没有消息就执行Handler.CallBack中的handleMessage(msg) } }
private static void handleCallback(Message message) { message.callback.run(); }
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
而我们的消息又是怎么初始化它又是怎么分辨出哪里发送来的消息呢?继续往下看
//这里只贴出 一个 obtainMessage() public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); }
PS:Message.obtain()这个函数就是用来准备消息的,而我们的Handler之所以能够分辨出来是哪个Activity发来的消息
是通过what和obj这两个参数来辨别出来的
消息有了分发消息有了还差发送消息了,平常我们发送消息有几种方式post()及postXXXX()和send()及sendXXXX(),
那么他们之间又有什么区别吗?
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); }
public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } 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); } 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);
//这里只贴出 一个 obtainMessage() public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); }
return false; } return enqueueMessage(queue, msg, 0);}
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); }
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } 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); } 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); }
post()及postXXXX() -----> sendMessage() ------> sendMessageDelayed() --------> sendMessageAtTime()
------>enqueueMessage()
enqueueMessage()又是什么鬼?? 接着往下看
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); //这个函数是不是很熟悉??? 这就回到了开头Handler的boolean } return queue.enqueueMessage(msg, uptimeMillis); }
此时将Handler引用赋值给了Message.target ,这样每个消息都有了这个Handler的引用
Handler初始化的Boolean参数开启的异步就是在这里开启的,启动Handler然后return queue.enqueueMessage(msg, uptimeMillis),至此消息进入队列,Handler类任务完成。下面开始讲MessageQueue
MessageQueue
承接上文我们直接跳到 enqueueMessage(msg, uptimeMillis) 函数,看看他都干了些什么?
boolean enqueueMessage(Message msg, long when) { ... synchronized (this) { if (mQuitting) { ... msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < p.when) { // 如果队列发生阻塞就唤醒 msg.next = p; mMessages = msg; needWake = mBlocked; } else { // 插入到队列中,不需要我们唤醒 // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. // 线程阻塞,p.target为null(即当前消息失去了handler)或者异步线程需要保持唤醒 needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }
重点来了,发送Handler是如何做到发送延时消息线程有不阻塞的呢?
首先判断的是消息是否退出,如果要退出就回收消息,然后获取到正在使用的消息并将传递过来的时间(即延时时间)赋值给msg.when。而p又是什么?其实p = mMessages第一次进来p是null,接着判断消息是否为null,当前消息的when是否为0或者小于p.when满足这个条件,p 就是下一个要执行的消息即(msg.next),再给needWake赋值时刻唤醒消息。如果不满足上面的条件即线程阻塞了开启一个死循环将其插入到队列中,让when = 0的消息或者when < p.when(即延时小的消息)先执行
到此整个消息队列是结束了,下面就是要讲讲Looper到底是如何工作的
Looper
Looper是什么?他是Android设计出来用来轮询消息的轮询器。是通过handler将其和消息产生关系。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Looper构造是私有的不能通过new方式实例化,而且构造中实例化了MessageQueue和当前线程,而Handler中持有的MessageQueue也是这里创建的引用从handler的构造中mQueue = mLooper.mQueue;就能看出继续往下看
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)); }Looper实例化是通过 Looper.prepare()方法完成的实例化。
而我们的Looper的工作在Handler被初始化的时候就开始工作了即构造函数调用了Looper.myLoop();
PS:这里不考虑handler构造传参Looper,其实构造传参Looper手动初始化Looper是一个样的
public static @Nullable Looper myLooper() { return sThreadLocal.get(); } // sThreadLocal.get() will return null unless you've called prepare(). // 这里解释是不调用Looper.prepare() sThreadLocal.get()为null static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
看代码说好的初始化呢??怎么是sThreadLocal没有看到Looper初始化啊?别急接着看sThreadLocal是干什么的,
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }
ThreadLocal.get()最终获取的是当前线程,当前线程是谁?哪来的?说好的实例化呢?怎么找不到Looper.prepare()其实在ActivityThread类的mian()中
public static final void main(String[] args) { ... Looper.prepareMainLooper(); //即这里已经开启了Looper if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); ... }
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
Fuck!!怎么会这样??说好的Handler初始化的时候Loop开始工作,其实我们都知道ActivityThread是Android程序的入口,在ActivityThread的main()中我们也没看到其他的东西都是做消息处理的,也就是说Handler,Looper在程序启动的时候就已经开始工作了,也就是说我们自己的ThreadLocal.get()获取的是ActivityThread线程即主线程,找到了Looper初始化的地方了,下面开启轮询
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) { // 没有消息就退出. return; } // This must be in a local variable, in case a UI event sets the logger // 必须在本地变量中,以防UI事件设置日志记录器 final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); //分发消息 end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { final long time = end - start; if (time > slowDispatchThresholdMs) { Slog.w(TAG, "Dispatch took " + time + "ms on " + Thread.currentThread().getName() + ", h=" + msg.target + " cb=" + msg.callback + " msg=" + msg.what); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // 确保在分发线程 // 线程表示没有被损坏 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(); } }