• 主线程 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 来执行。

  • 相关阅读:
    Redis(二)
    Redis(一)
    MyBatis--一级二级缓存
    MySQL优化
    HashMap
    ArrayList
    常用框架注解说明
    Linux常用基础命令
    SpringCloud--gateway路由配置
    JetBrains系列软件的插件安装
  • 原文地址:https://www.cnblogs.com/ly570/p/11513077.html
Copyright © 2020-2023  润新知