主线程 Looper.loop() 死循环为何不会ANR

先看下 ActivityThread 中的这段代码:

 

而 loop() 方法中,存在一个死循环:

public static void loop() {
...
...
...

for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}

...
...
...

}
}
如果 ActivityThread 中的 main() 方法没有 Looper.loop() 进行循环,那么 ActivityThread 运行完毕就会退出,相应的应用也就退出了。这就是这个死循环存在的必要性。

而ActivityThread 并不是一个Thread。而主线程就是从main 方法开始。在这个类中有个内部类 H,继承 Handler,内部有handleMessage 方法:

class H extends Handler {

...
...
...

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);
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;
...
...
}



...
...
...

}
在此方法中,有 handleLaunchActivity,handleRelaunchActivity,handlePauseActivity ... 等方法,是不是跟 Activity 的生命周期非常的相似呢?

选择其中一个 handlePauseActivity  方法来追:

private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}

r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}

// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
再看以下几个方法:


final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {

...

// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}

performPauseActivityIfNeeded(r, reason);

...
}

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {

...

try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
...
}
 从最后一个方法里面,调用了 mInstrumentation.callActivityOnPause(r.activity);

在类 Instrumentation 中的 callActivityOnPause 方法如下:

/**
* Perform calling of an activity's {@link Activity#onPause} method. The
* default implementation simply calls through to that method.
*
* @param activity The activity being paused.
*/
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
Activity 类中的 performPause 方法如下:

final void performPause() {
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
}
在这里看到了熟悉的生命周期中的方法 onPause() 。由此可以看出 Activity的生命周期不过就是Looper 传递消息中的某一个消息而已,所以Looper中的死循环不仅不会造成ANR,反而 Activity 的生命周期还要靠 Looper 来执行。

posted on 2019-09-12 17:26  激流勇进1  阅读(566)  评论(0编辑  收藏  举报