Looper.loop()会阻塞主线程吗
答案是肯定的,主线程的loop会阻塞主线程,不过这并不是问题,那么原因是什么呢?
ActivityThread 是App的入口,这里可以看到 main 方法,它是整个java程序的入口。ActivitvThread 的 main 方法主要作用是消息循环,一旦消息循环停止,那么程序也就可以退出了。
我们必须明白,Android是事件驱动的,在Loop.loop0中不断接收、处理事件,才能保证Android的生命周期执行下去,而Activity的生命周期都由主线程的Loop.loop0来调度。
很显然当目前没有事件需要处理的时候,主线程就会阻塞,当子线程向消息队列发送消息,主线程就被唤醒。
主线程的loope如果没有消息,那么loop里面就会被 messageQueue 阻塞。因为Android系统是事件驱动的,所以我们写的代码就是通过handler驱动起来的,我们activity的生命周期方法,包括我们的UI绘制的信号,这些UI绘制的事件都是通过Handler Looper循环内部发起的。
这些所有的事务都被封装成为了一个一个的message,然后通过loper来调用handleMessage回调到主线程,所以我们的代码就是在循环里面执行的,也就是主线程一切皆Message。
ActivityThread 的 main 方法主要作用就是做消息循环,一旦退出消息循环,那么程序也就可以退出了。
从消息队列中取消息可能会引起阻塞,取到消息会做出相应的处理。如果某个消息执行时间过长,就可能会影响 UI 线程的刷新效率,造成卡顿的现象
死循环问题
Looper.loor()
方法中会调用死循环去从MessageQueue中读取message
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//死循环,其中loopOnce中调用了messageQueue.next()方法读取消息
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block可能阻塞的
}
如上代码loop.looper()
死循环调用MessageQueue.next()
读取消息
死循环会不会导致我们的CPU在我们没消息的时候在那里空转呢?实际上如果你没有什么事情可做,那么MessageQueue里面有一个nativePollOnce的这个方法,这个方法是个native方法,本地方法调用这个方法其实就是调用Linux里面的一个管道机制epoll。没有消息的时候,调用epoll wait,它就会等待在那里,实际上调用完wait之后,就会释放我们的CPU,就等于我们的应用在休眠状态,它不会让CPU一直在那里空转。