Android知识总结
Android中UI的更新在主线程中完成,为了避免ANR异常所以耗时的操作需要在子线程中完成。由于主线程和子线程中需要消息的传递就引入了Hander消息传递机制。
一、首先看一下handler的使用过程
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
***
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.sendEmptyMessage("0");
}
}).start();
}
}
二、handler运行机制
handler之间的通信可见下面两张图:
Handler机制也可叫异步消息机制,它主要由4个部分组成:Message,Handler,MessageQueue,Looper,其中增加了ThreadLocal来管理Looper.
1.Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。使用Message的arg1和arg2便可携带int数据,使用obj便可携带Object类型数据。target用来保存当前的handler。
2.Handler
Handler顾名思义就是处理者的意思,它只要用于在子线程发送消息对象Message,在UI线程处理消息对象Message,在子线程调用sendMessage方法发送消息对象Message,而发送的消息经过一系列地辗转之后最终会被传递到Handler的handleMessage方法中,最终在handleMessage方法中消息对象Message被处理。
3.MessageQueue
MessageQueue就是消息队列的意思,它只要用于存放所有通过Handler发送过来的消息。这部分消息会一直存放于消息队列当中,等待被处理。每个线程中只会有一个MessageQueue对象,请牢记这句话。其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。
4.Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当MesssageQueue中存在一条消息,Looper就会将这条消息取出,并将它传递到Handler的handleMessage()方法中。每个线程只有一个Looper对象。
5.ThreadLocal
通过引用ThreadLocalMap的map对象来管理不同线程中的Looper。通过get()/set()方法来获取和存储Looper.
三、handler源码分析
1、发送消息
使用Handler发送消息主要有两种,一种是sendXXXMessage方式,还有一个postXXX方式,不过两种方式最后都会调用到sendMessageDelayed方法,所以我们就以最简单的sendMessage()方法来分析。
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
调用sendMessageDelayed()方法,默认delayMillis为0
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
在调用sendMessageAtTime时,传入的时间值: 系统时钟+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;
}
// 调用enqueueMessage,把消息加入到MessageQueue中
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//msg.target标记为当前Handler对象
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在MessageQueue中把接受到的Message存到MessageQueue中。然后根据延迟的时间片when把不同得消息存放到Message单链表中,按延迟的时间从小到大从链表头部依次排列。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
// 判断消息队列是否正在被关闭,如果是正在被关闭,则return false告诉消息入队
//是失败,并且回收消息
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();
return false;
}
//设置msg的when并且修改msg的标志位,msg标志位显示为已使用
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//根据when的比较来判断要添加的Message是否应该放在队列头部,当第一个添加消息的时候,
// 测试队列为空,所以该Message也应该位于头部。
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
// 把msg的下一个元素设置为p
msg.next = p;
// 把msg设置为链表的头部元素
mMessages = msg;
// 如果有阻塞,则需要唤醒
needWake = mBlocked;
} else {
//除非消息队列的头部是障栅(barrier),或者消息队列的第一个消息是异步消息,
//否则如果是插入到中间位置,我们通常不唤醒消息队列,
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
// 不断遍历消息队列,根据when的比较找到合适的插入Message的位置。
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;
} //将消息放到消息头
if (needWake) {
nativeWake(mPtr); //在这里进行唤醒
}
}
return true;
}
2、读取消息
Looper.loop()的作用就是:从当前线程的MessageQueue从不断取出Message,并调用其相关的方法。代码如下:
public static void loop() {
//1、里面调用了sThreadLocal.get()获得刚才创建的Looper对象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//2、获取消息队列, 如果Looper为空则会抛出异常
final MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
***
for (;;) {
//3、通过死循环读取MessageQueue中的Message
Message msg = queue.next(); // might block
if (msg == null) {
//由于刚创建MessageQueue就开始轮询,队列里有消息的,等到Handler sendMessageenqueueMessage后队列里才有消息
return;
}
***
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
//4、通过Message中的target找到当前Message中的Handler分发消息
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
***
//5、回收资源
msg.recycleUnchecked();
}
}
首先还是判断了当前线程是否有Looper,然后得到当前线程的MessageQueue。接下来,就是最关键的代码了,写了一个死循环,不断调用MessageQueue的next方法取出MessageQueue中的Message,注意,当MessageQueue中没有消息时,next方法会阻塞,导致当前线程挂起。
拿到Message以后,会调用它的target的dispatchMessage方法,这个target其实就是发送消息时用到的Handler。所以就是调用Handler的dispatchMessage方法,代码如下:
public void dispatchMessage(Message msg) {
// 如果msg.callback不是null,则调用handleCallback
if (msg.callback != null) {
handleCallback(msg);
} else {
// 如果 mCallback不为空,则调用mCallback.handleMessage方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 调用Handler自身的handleMessage,这就是我们常常重写的那个方法
handleMessage(msg);
}
}
public void handleMessage(Message msg) {
}
回收Message, 调用Message中的recycleUnchecked方法:
//最大队列个数为50
private static final int MAX_POOL_SIZE = 50;
private static Message sPool;
@UnsupportedAppUsage
void recycleUnchecked() {
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
//把message放在链表的头部
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
//把message放在sPool中构成一个链表回路
//运用享元设计模式,提供内存复用,避免内存抖动造成的OOM
sPool = this;
sPoolSize++;
}
}
}
3、ActivityThread
主线程中在ActivityThread的main方法中创建Looper对象,所以在主线程中创建Hander时不用创建Looper对象。在子线程中需要手动创建Looper对象。
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("");
//1、创建Looper,并将Looper保存到ThreadLocal中
Looper.prepareMainLooper();
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
//把ActivityThread 和主线程进行绑定
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//2、开启死循环读取消息
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
4、Looper机制
创建Looper
public static void prepare() {
//消息队列可以quit
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//不为空表示当前线程已经创建了Looper
if (sThreadLocal.get() != null) {
//每个线程只能创建一个Looper
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建Looper并设置给sThreadLocal,这样get的时候就不会为null了
sThreadLocal.set(new Looper(quitAllowed));
}
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
从上面的代码可以看出,一个线程最多只有一个Looper对象。当没有Looper对象时,去创建一个Looper,并存放到sThreadLocal中。
private Looper(boolean quitAllowed) {
//创建了MessageQueue
mQueue = new MessageQueue(quitAllowed);
//当前线程的绑定
mThread = Thread.currentThread();
}
这里主要就是创建了消息队列MessageQueue,并让它供Looper持有,因为一个线程最大只有一个Looper对象,所以一个线程最多也只有一个消息队列。然后再把当前线程赋值给mThread。
MessageQueue的构造方法没有什么可讲的,它就是一个消息队列,用于存放Message。
所以Looper.prepare()的作用主要有以下三点
1、创建Looper对象
2、创建MessageQueue对象,并让Looper对象持有
3、让Looper对象持有当前线程
5、ThreadLocal
通过引用ThreadLocalMap的map对象来管理不同线程中的Looper。通过get()/set()方法来获取和存储Looper.
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
6、Message
成员变量
// 回复跨进程的Messenger
public Messenger replyTo;
// Messager发送这的Uid
public int sendingUid = -1;
// 正在使用的标志值 表示当前Message 正处于使用状态,当Message处于消息队列中、
//处于消息池中或者Handler正在处理Message的时候,它就处于使用状态。
/*package*/ static final int FLAG_IN_USE = 1 << 0;
// 异步标志值 表示当前Message是异步的。
/*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;
// 消息标志值 在调用copyFrom()方法时,该常量将会被设置,其值其实和FLAG_IN_USE一样
/*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
// 消息标志,上面三个常量 FLAG 用在这里
/*package*/ int flags;
// 用于存储发送消息的时间点,以毫秒为单位
/*package*/ long when;
// 用于存储比较复杂的数据
/*package*/ Bundle data;
// 用于存储发送当前Message的Handler对象,前面提到过Handler其实和Message相互持有引用的
/*package*/ Handler target;
// 用于存储将会执行的Runnable对象,前面提到过除了handlerMessage(Message msg)
//方法,你也可以使用Runnable执行操作,要注意的是这种方法并不会创建新的线程。
/*package*/ Runnable callback;
// 指向下一个Message,也就是线程池其实是一个链表结构
/*package*/ Message next;
// 该静态变量仅仅是为了给同步块提供一个锁而已
private static final Object sPoolSync = new Object();
//该静态的Message是整个线程池链表的头部,通过它才能够逐个取出对象池的Message
private static Message sPool;
// 该静态变量用于记录对象池中的Message的数量,也就是链表的长度
private static int sPoolSize = 0;
// 设置了对象池中的Message的最大数量,也就是链表的最大长度
private static final int MAX_POOL_SIZE = 50;
//该版本系统是否支持回收标志位
private static boolean gCheckRecycle = true;
获取消息
public static Message obtain() {
// 保证线程安全
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
// flags为移除使用标志
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
public static Message obtain(Handler h) {
Message m = obtain();
//记录Hander对象
m.target = h;
return m;
}
7、MessageQueue成员变量
//用于标示消息队列是否可以被关闭,主线程的消息队列不可关闭
private final boolean mQuitAllowed;
@SuppressWarnings("unused")
// 该变量用于保存native代码中的MessageQueue的指针
private long mPtr; // used by native code
//在MessageQueue中,所有的Message是以链表的形式组织在一起的,该变量保存了
//链表的第一个元素,也可以说它就是链表的本身
Message mMessages;
//当Handler线程处于空闲状态的时候(MessageQueue没有其他Message时),可以利用
//它来处理一些事物,该变量就是用于保存这些空闲时候要处理的事务
private final ArrayList mIdleHandlers = new ArrayList();
// 注册FileDescriptor以及感兴趣的Events,例如文件输入、输出和错误,设置回调函数,最后
// 调用nativeSetFileDescriptorEvent注册到C++层中,
// 当产生相应事件时,由C++层调用Java的DispathEvents,激活相应的回调函数
private SparseArray mFileDescriptorRecords;
// 用于保存将要被执行的IdleHandler
private IdleHandler[] mPendingIdleHandlers;
//标示MessageQueue是否正在关闭。
private boolean mQuitting;
// 标示 MessageQueue是否阻塞
private boolean mBlocked;
// 在MessageQueue里面有一个概念叫做障栅,它用于拦截同步的Message,阻止这些消息被执行,
// 只有异步Message才会放行。障栅本身也是一个Message,只是它的target为null并且arg1用于区分不同的障栅,
// 所以该变量就是用于不断累加生成不同的障栅。
private int mNextBarrierToken;
next()方法
//销毁
private native static void nativeDestroy(long ptr);
//延时
private native void nativePollOnce(long ptr, int timeoutMillis);
//唤醒
private native static void nativeWake(long ptr);
Message next() {
// 如果消息循环已经退出了。则直接在这里return。因为调用disposed()方法后mPtr=0
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//记录空闲时处理的IdlerHandler的数量
int pendingIdleHandlerCount = -1; // -1 only during first iteration
// native层用到的变量 ,如果消息尚未到达处理时间,则表示为距离该消息处理事件的总时长,
// 表明Native Looper只需要block到消息需要处理的时间就行了。 所以nextPollTimeoutMillis>0表示还有消息待处理
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
//刷新下Binder命令,一般在阻塞前调用
Binder.flushPendingCommands();
}
// 调用native层进行消息标示,nextPollTimeoutMillis 为0立即返回,为-1则阻塞等待, 大于0延时一定时间。
nativePollOnce(ptr, nextPollTimeoutMillis);
//加上同步锁
synchronized (this) {
// Try to retrieve the next message. Return if found.
// 获取开机到现在的时间
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
// 获取MessageQueue的链表表头的第一个元素
Message msg = mMessages;
// 判断Message是否是障栅,如果是则执行循环,拦截所有同步消息,直到取到第一个异步消息为止
if (msg != null && msg.target == null) {
// 如果能进入这个if,则表面MessageQueue的第一个元素就是障栅(barrier)
// 循环遍历出第一个异步消息,这段代码可以看出障栅会拦截所有同步消息
do {
prevMsg = msg;
msg = msg.next;
//如果msg==null或者msg是异步消息则退出循环,msg==null则意味着已经循环结束
} while (msg != null && !msg.isAsynchronous());
}
// 判断是否有可执行的Message
if (msg != null) {
// 判断该Mesage是否到了被执行的时间。
if (now < msg.when) {
// 当Message还没有到被执行时间的时候,记录下一次要执行的Message的时间点
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Message的被执行时间已到
// Got a message.
// 从队列中取出该Message,并重新构建原来队列的链接
// 刺客说明说有消息,所以不能阻塞
mBlocked = false;
// 如果还有上一个元素
if (prevMsg != null) {
//上一个元素的next(越过自己)直接指向下一个元素
prevMsg.next = msg.next;
} else {
//如果没有上一个元素,则说明是消息队列中的头元素,直接让第二个元素变成头元素
mMessages = msg.next;
}
// 因为要取出msg,所以msg的next不能指向链表的任何元素,所以next要置为null
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
// 标记该Message为正处于使用状态,然后返回Message
msg.markInUse();
return msg;
}
} else {
// No more messages.
// 没有任何可执行的Message,重置时间
nextPollTimeoutMillis = -1;
}
// 关闭消息队列,返回null,通知Looper停止循环, 只有在子线程中可以调用用
if (mQuitting) {
dispose();
return null;
}
// 当第一次循环的时候才会在空闲的时候去执行IdleHandler,从代码可以看出所谓的空闲状态
// 指的就是当队列中没有任何可执行的Message,这里的可执行有两要求,
// 即该Message不会被障栅拦截,且Message.when到达了执行时间点
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
// 这里是消息队列阻塞( 死循环) 的重点,消息队列在阻塞的标示是消息队列中没有任何消息,
// 并且所有的 IdleHandler 都已经执行过一次了
if (pendingIdleHandlerCount <= 0) {
mBlocked = true;
continue;
}
// 初始化要被执行的IdleHandler,最少4个
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 开始循环执行所有的IdleHandler,并且根据返回值判断是否保留IdleHandler
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// 重点代码,IdleHandler只会在消息队列阻塞之前执行一次,执行之后改标示设置为0,
// 之后就不会再执行,一直到下一次调用MessageQueue.next() 方法。
pendingIdleHandlerCount = 0;
// 当执行了IdleHandler 的 处理之后,会消耗一段时间,这时候消息队列里的可能有消息已经到达
// 可执行时间,所以重置该变量回去重新检查消息队列。
nextPollTimeoutMillis = 0;
}
}
private void dispose() {
if (mPtr != 0) {
//退出时调用native方法,关闭消息队列
nativeDestroy(mPtr);
mPtr = 0;
}
}
Handler线程里面实际上有两个无线循环体,Looper循环体和MessageQueue循环体,真正阻塞的地方是MessageQueue的next()方法里。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
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();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// 如果当前时间片小于p.when,加入队列头部
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//给据时间片的大小,加入队列
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;
}
// 如果处于等待状态,唤醒
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Looper退出
Looper
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
MessageQueue
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
//退出时标志为至true
mQuitting = true;
//清楚队列中的消息
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
nativeWake(mPtr);
}
}
private void removeAllMessagesLocked() {
Message p = mMessages;
while (p != null) {
Message n = p.next;
p.recycleUnchecked();
p = n;
}
mMessages = null;
}
private void removeAllFutureMessagesLocked() {
final long now = SystemClock.uptimeMillis();
Message p = mMessages;
if (p != null) {
if (p.when > now) {
removeAllMessagesLocked();
} else {
Message n;
for (;;) {
n = p.next;
if (n == null) {
return;
}
if (n.when > now) {
break;
}
p = n;
}
p.next = null;
do {
p = n;
n = p.next;
p.recycleUnchecked();
} while (n != null);
}
}
}
四、runWithScissors 同步执行
Handler 的 setxx
或者 postxx
发送消息是异步的并不会阻塞程序的执行。runWithScissors
是同步消息,可以通过阻塞的方式,向目标线程发送任务,并等待任务执行结束。
public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
//把任务赋值给mTask
mTask = task;
}
@Override
public void run() {
try {
//执行这个任务
mTask.run();
} finally {
synchronized (this) {
//任务执行完毕,标记mDone为true,并唤醒等待线程
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
//把本身的BlockingRunnable发送到handler线程中执行
if (!handler.post(this)) {
return false;
}
synchronized (this) {
if (timeout > 0) {
final long expirationTime =
SystemClock.uptimeMillis() + timeout;
while (!mDone) {
long delay = expirationTime - SystemClock.uptimeMillis();
if (delay <= 0) {//超时返回
return false; // timeout
}
try {//否则一直等待
wait(delay);
} catch (InterruptedException ex) {
}
}
} else {//如果没有设置超时,则一直等待
while (!mDone) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
由此可见使用 runWithScissors() 可能造成调用线程进入阻塞,而得不到唤醒,如果当前持有别的锁,还会造成死锁。