// 子线程创建 new Thread(new Runnable() { @Override publicvoidrun(){ handler2 = new Handler(); } }).start();
在子线程中直接创建会抛异常
ErrorMessage
1
Can't create handler inside thread that has not called Looper.prepare()
需要再子线程创建Handler之前 调用 Looper.prepare
1 2 3 4 5 6 7 8
// 子线程创建 new Thread(new Runnable() { @Override publicvoidrun(){ Looper.prepare(); handler2 = new Handler(); } }).start();
不同线程下写法不同的原因
Handler 层面
打开Handler的源码 在构造方法中 有一段获取当前的Loop对象的逻辑
1 2 3
mLooper = Looper.myLooper(); if (mLooper == null) { thrownew RuntimeException("Can't create handler inside thread that has not called Looper.prepare()"); }
publicstaticvoidprepare(){ prepare(true); } privatestaticvoidprepare(boolean quitAllowed){ if (sThreadLocal.get() != null) { thrownew RuntimeException("Only one Looper may be created pe r thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
publicbooleansendMessageAtTime(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); returnfalse; } return enqueueMessage(queue, msg, uptimeMillis);}
privatebooleanenqueueMessage(MessageQueue queue, Message msg, long uptimeMillis){ msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
booleanenqueueMessage(Message msg, long when){ if (msg.target == null) {//msg.target就是发送此消息的Handler thrownew IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) {//表示此消息正在被使用 thrownew IllegalStateException(msg + " This message is already in use."); }
synchronized (this) { if (mQuitting) {//表示此消息队列已经被放弃了 IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); returnfalse; }
msg.markInUse(); msg.when = when;//将延迟时间封装到msg内部 Message p = mMessages;//消息队列的第一个元素 boolean needWake; if (p == null || when == 0 || when < p.when) { //如果此队列中头部元素是null(空的队列,一般是第一次),或者此消息不是延时的消息,则此消息需要被立即处理,此时会将这个消息作为新的头部元素,并将此消息的next指向旧的头部元素,然后判断如果Looper获取消息的线程如果是阻塞状态则唤醒它,让它立刻去拿消息处理 msg.next = p; mMessages = msg; needWake = mBlocked; } else { //如果此消息是延时的消息,则将其添加到队列中,原理就是链表的添加新元素,按照when,也就是延迟的时间来插入的,延迟的时间越长,越靠后,这样就得到一条有序的延时消息链表,取出消息的时候,延迟时间越小的,就被先获取了。插入延时消息不需要唤醒Looper线程。
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); } } returntrue; }
源码中用 mMessages 代表当前等待处理的消息,MessageQueue 也 没有使用一个集合保存所有的消息。观察中间的代码部分,队列中根据时间 when 来时间排序,这个时间也就是我们传进来延迟的时间uptimeMills 参数,之后再根据时间的顺序调用 msg.next,从而指定下一个将要处理的消息是什么,最后判断消息是否要处理,是否要唤醒线程
publicstaticvoidloop(){ // 获取当前的Looper 对象 final Looper me = myLooper(); if (me == null) { thrownew RuntimeException("No Looper; Looper.prepare() wasn't ca lled on this thread."); } // 获取当前要处理的数据 final MessageQueue queue = me.mQueue;
next() { //... for (;;) { //... nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // Try to retrieve the next message. Return if found. finallong now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; //... if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake u p when it is ready. nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // Got a message. mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; return msg; } } else { // No more messages. nextPollTimeoutMillis = -1; } // Process the quit message now that all pending messages hav e been handled. if (mQuitting) { dispose(); returnnull; } } } }