ActivityThread 是应用程序的入口,在 ActivityThread 中的 main 方法是整个java程序的入口。ActivityThread 的 main 方法主要就是做消息循环,一旦退出消息循环,那么你的程序也就可以退出了。
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
initPCArgs(thread, args);
thread.attach(false);
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在 main 方法中会创建一个主线程的 Looper 对象,而loop源码中是一个死循环在遍历消息队列来取消息。
其实整个 Android 系统就是在一个Looper.loop() 循环的,整个Android的一切都是以Handler 机制进行的,即只要有代码执行都是通过Handler来执行的,而所谓ANR便是Looper.loop没有得到及时处理,一旦没有消息需要处理时,主线程就会被阻塞休眠,当子线程往消息队列发送消息,并且往管道文件写数据时,主线程就被唤醒。
这里涉及到了Linux的 pipe/epoll 机制,在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce() 方法里,此时主线程会释放CPU的资源进入休眠状态,直到下一个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立即通知相应程序进行读或写操作。
在Handler消息处理机制中有每个activity生命周期状态所对应的case,通过switch生命周期状态,loop循环里会分发消息给Handler,从而执行对应的代码,并不会导致loop的卡死。
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, false, (args.argi1 & USER_LEAVING) != 0, args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY_FINISHING: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
SomeArgs args = (SomeArgs) msg.obj;
handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case STOP_ACTIVITY_SHOW: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
SomeArgs args = (SomeArgs) msg.obj;
handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
总结:
ActivityThread的 main 方法的主要作用就是做消息循环,一旦退出消息循环,主线程运行完毕,那么你的应用也就退出了。Android是事件驱动的,在Looper.loop()中不断接收事件、处理事件,而Activity的生命周期都依靠于主线程的 Loop.loop() 来调度,所以可想而知它的存活周期和 Activity 也是一致的。当没有事件需要处理时,主线程就会阻塞;当子线程往消息队列发送消息,并且往管道文件写数据时,主线程就被唤醒。真正会卡死主线程的操作是在执行回调方法 onCreate/onStart/onResume 等操作的时间过长,导致掉帧,甚至发生ANR,looper.loop() 本身不会导致应用卡死。
主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗。