Android Q之Activity OnStop回调时机

2019-10-14  本文已影响0人  android_coder

Anroid Q 之onStop执行时机
我们都知道在activity切换过程中,譬如A启动到BActivity,在启动完成之后一般的A会回调其onStop生命周期,那么我们就来看看何时以及何种情况下A的onStop会被回调

1:停止Activity的流程

1:在resume具体的activity时,当目标进程的ActivityThread的handleResumeActivity之后,会创建一个Idler,并且添加到主线程的消息队列中去

if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
      WindowManager.LayoutParams l = r.window.getAttributes();
      if ((l.softInputMode
            & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
              != forwardBit) {
          l.softInputMode = (l.softInputMode
                    & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                    | forwardBit;
         if (r.activity.mVisibleFromClient) {
                ViewManager wm = a.getWindowManager();
                View decor = r.window.getDecorView();
                wm.updateViewLayout(decor, l);
          }
        }
        r.activity.mVisibleFromServer = true;
        mNumVisibleActivities++;
        if (r.activity.mVisibleFromClient) {
            r.activity.makeVisible();
        }
    }
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());------->Looper对应的是主线程的Looper,消息队列是主线程的

2:handleResumeActivity执行之后已经完成了启动activity的所有动作,接下来就是Idle状态了,此时可以执行一些Idle的行为,而Idler类内部处理函数会调用activityIdle方法

private class Idler implements MessageQueue.IdleHandler {
    @Override
    public final boolean queueIdle() {
        ActivityClientRecord a = mNewActivities;
        boolean stopProfiling = false;
        if (mBoundApplication != null && mProfiler.profileFd != null
                && mProfiler.autoStopProfiler) {
            stopProfiling = true;
        }
     if (a != null) {
            mNewActivities = null;
            IActivityTaskManager am = ActivityTaskManager.getService();
            ActivityClientRecord prev;
            do {
                if (localLOGV) Slog.v(
                    TAG, "Reporting idle of " + a +
                    " finished=" +
                    (a.activity != null && a.activity.mFinished));
                if (a.activity != null && !a.activity.mFinished) {
                    try {
                        am.activityIdle(a.token, a.createdConfig, stopProfiling);---->调用activityIdle方法
                        a.createdConfig = null;
                    } catch (RemoteException ex) {
                        throw ex.rethrowFromSystemServer();
                    }
                }
                prev = a;
                a = a.nextIdle;
                prev.nextIdle = null;
            } while (a != null);
     }
     if (stopProfiling) {
            mProfiler.stopProfiling();
     }
     applyPendingProcessState();
     return false;
    }
}

3:activityIdle的具体实现

进入到ActivityTaskManagerService.java

@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    final long origId = Binder.clearCallingIdentity();
    try {
        WindowProcessController proc = null;
        synchronized (mGlobalLock) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);--->根据token获取对应的Stack
            if (stack == null) {
                return;
            }
            final ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token,
                    false /* fromTimeout */, false /* processPausingActivities */, config);
            if (r != null) {
                proc = r.app;
            }
            if (stopProfiling && proc != null) {
                proc.clearProfilerIfNeeded();
            }
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

4:ActivityStackSuperVisor的activityIdleInternalLocked

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
        boolean processPausingActivities, Configuration config) {
    ......................................
    ActivityRecord r = ActivityRecord.forTokenLocked(token);----->获取ActivityRecord对象
    if (r != null) {
        if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
                + Debug.getCallers(4));
        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
        r.finishLaunchTickingLocked();
        if (fromTimeout) {
            reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY,
                    -1 /* launchState */);
        }

        // This is a hack to semi-deal with a race condition
        // in the client where it can be constructed with a
        // newer configuration from when we asked it to launch.
        // We'll update with whatever configuration it now says
        // it used to launch.
        if (config != null) {
            r.setLastReportedGlobalConfiguration(config);
        }

        // We are now idle.  If someone is waiting for a thumbnail from
        // us, we can now deliver.
        r.idle = true;

        //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);

        // Check if able to finish booting when device is booting and all resumed activities
        // are idle.
        if ((mService.isBooting() && mRootActivityContainer.allResumedActivitiesIdle())
                || fromTimeout) {
            booting = checkFinishBootingLocked();
        }

        // When activity is idle, we consider the relaunch must be successful, so let's clear
        // the flag.
        r.mRelaunchReason = RELAUNCH_REASON_NONE;
    }

    if (mRootActivityContainer.allResumedActivitiesIdle()) {
        if (r != null) {
            mService.scheduleAppGcsLocked();
        }

        if (mLaunchingActivityWakeLock.isHeld()) {
            mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
            if (VALIDATE_WAKE_LOCK_CALLER &&
                    Binder.getCallingUid() != Process.myUid()) {
                throw new IllegalStateException("Calling must be system uid");
            }
            mLaunchingActivityWakeLock.release();
        }
        mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
    }

    // Atomically retrieve all of the other things to do.
    final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
            true /* remove */, processPausingActivities);----------->处理stopping状态的activity
    NS = stops != null ? stops.size() : 0;
    if ((NF = mFinishingActivities.size()) > 0) {
        finishes = new ArrayList<>(mFinishingActivities);
        mFinishingActivities.clear();
    }

    if (mStartingUsers.size() > 0) {
        startingUsers = new ArrayList<>(mStartingUsers);
        mStartingUsers.clear();
    }

    // Stop any activities that are scheduled to do so but have been
    // waiting for the next one to start.
    for (int i = 0; i < NS; i++) {
        r = stops.get(i);
        final ActivityStack stack = r.getActivityStack();
        if (stack != null) {
            if (r.finishing) {----------------->如果正处于finishing状态
                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
                        "activityIdleInternalLocked");
            } else {
                stack.stopActivityLocked(r);------->停止该activity
            }
        }
    }

    // Finish any activities that are scheduled to do so but have been
    // waiting for the next one to start.
    for (int i = 0; i < NF; i++) {
        r = finishes.get(i);----------------------------------------->处理finish状态的activity
        final ActivityStack stack = r.getActivityStack();
        if (stack != null) {
            activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
        }
    }

    if (!booting) {
        // Complete user switch
        if (startingUsers != null) {
            for (int i = 0; i < startingUsers.size(); i++) {
                mService.mAmInternal.finishUserSwitch(startingUsers.get(i));
            }
        }
    }

    mService.mH.post(() -> mService.mAmInternal.trimApplications());
    //dump();
    //mWindowManager.dump();

    if (activityRemoved) {
        mRootActivityContainer.resumeFocusedStacksTopActivities();
    }

    return r;
}

5:ActivityStack之stopActivityLocked

final void stopActivityLocked(ActivityRecord r) {
    if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
    //如果intent中有FLAG_ACTIVITY_NO_HISTORY获取ActivityInfo中有FLAG_NO_HISTORY
    那么调用requestFinishActivityLocked销毁该activity,也就是说如果从A---->B--->C,
    如果B包含该flag,那么从C直接返回到了A
    if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
            || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
        if (!r.finishing) {
            if (!shouldSleepActivities()) {
                if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
                if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                        "stop-no-history", false)) {
                    // If {@link requestFinishActivityLocked} returns {@code true},
                    // {@link adjustFocusedActivityStack} would have been already called.
                    r.resumeKeyDispatchingLocked();
                    return;
                }
            } else {
                if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r
                        + " on stop because we're just sleeping");
            }
        }
    }

    if (r.attachedToProcess()) {----->如果r的进程和主线程都存在
        adjustFocusedActivityStack(r, "stopActivity");---->调整焦点activity
        r.resumeKeyDispatchingLocked();---------->暂时允许r接受事件
        try {
            r.stopped = false;
            if (DEBUG_STATES) Slog.v(TAG_STATES,
                    "Moving to STOPPING: " + r + " (stop requested)");
            r.setState(STOPPING, "stopActivityLocked");---->设置成stopping状态
            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                    "Stopping visible=" + r.visible + " for " + r);
            if (!r.visible) {
                r.setVisible(false);----->设置成不可见
            }
            EventLogTags.writeAmStopActivity(
                    r.mUserId, System.identityHashCode(r), r.shortComponentName);
            //事务StopActivityItem
            mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
                    StopActivityItem.obtain(r.visible, r.configChangeFlags));
            if (shouldSleepOrShutDownActivities()) {
                r.setSleeping(true);
            }
            Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);----->设置超时消息
            mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
        } catch (Exception e) {
            // Maybe just ignore exceptions here...  if the process
            // has crashed, our death notification will clean things
            // up.
            Slog.w(TAG, "Exception thrown during pause", e);
            // Just in case, assume it to be stopped.
            r.stopped = true;
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
            r.setState(STOPPED, "stopActivityLocked");
            if (r.deferRelaunchUntilPaused) {
                destroyActivityLocked(r, true, "stop-except");
            }
        }
    }
}

6:LifecycleManager处理scheduleTransaction

这里我们在activity启动过程中已经分析过,最终调用的ActivityLifecycleItem的execute方法

public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
    client.handleStopActivity(token, mShowWindow, mConfigChanges, pendingActions,
            true /* finalStateRequest */, "STOP_ACTIVITY_ITEM");---->回调ActivityThread的handleStopActivity方法
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

7:ActivityThread的handleStopActivity

 public void handleStopActivity(IBinder token, boolean show, int configChanges,
        PendingTransactionActions pendingActions, boolean finalStateRequest, String reason) {
    final ActivityClientRecord r = mActivities.get(token);
    r.activity.mConfigChangeFlags |= configChanges;

    final StopInfo stopInfo = new StopInfo();
    performStopActivityInner(r, stopInfo, show, true /* saveState */, finalStateRequest,
            reason);-------------------------->会回调onStop方法

    if (localLOGV) Slog.v(
        TAG, "Finishing stop of " + r + ": show=" + show
        + " win=" + r.window);

    updateVisibility(r, show);----------------------->更新可见性

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

    stopInfo.setActivity(r);
    stopInfo.setState(r.state);
    stopInfo.setPersistentState(r.persistentState);
    pendingActions.setStopInfo(stopInfo);
    mSomeActivitiesChanged = true;
}

8:performStopActivityInner

private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown,
        boolean saveState, boolean finalStateRequest, String reason) {
    if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
    if (r != null) {
        if (!keepShown && r.stopped) {
            if (r.activity.mFinished) {------------------------------->如果已经stopped了,不做处理
                // If we are finishing, we won't call onResume() in certain
                // cases.  So here we likewise don't want to call onStop()
                // if the activity isn't resumed.
                return;
            }
            if (!finalStateRequest) {
                final RuntimeException e = new RuntimeException(
                        "Performing stop of activity that is already stopped: "
                                + r.intent.getComponent().toShortString());
                Slog.e(TAG, e.getMessage(), e);
                Slog.e(TAG, r.getStateString());
            }
        }

        // One must first be paused before stopped...
        performPauseActivityIfNeeded(r, reason);----------------->先onPause,该方法是判断是否需要onPause

        if (info != null) {
            try {
                // First create a thumbnail for the activity...
                // For now, don't create the thumbnail here; we are
                // doing that by doing a screen snapshot.
                info.setDescription(r.activity.onCreateDescription());
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                            "Unable to save state of activity "
                            + r.intent.getComponent().toShortString()
                            + ": " + e.toString(), e);
                }
            }
        }

        if (!keepShown) {--------------------------------->如果不需要保持可见,那么才回调
            callActivityOnStop(r, saveState, reason);
        }
    }
}

9:callActivityOnStop

private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
    // Before P onSaveInstanceState was called before onStop, starting with P it's
    // called after. Before Honeycomb state was always saved before onPause.
    final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
            && !r.isPreHoneycomb();
    final boolean isPreP = r.isPreP();
    if (shouldSaveState && isPreP) {
        callActivityOnSaveInstanceState(r);--------------------->保存状态
    }

    try {
        r.activity.performStop(r.mPreserveWindow, reason);------>回调activity的onStop方法
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(r.activity, e)) {
            throw new RuntimeException(
                    "Unable to stop activity "
                            + r.intent.getComponent().toShortString()
                            + ": " + e.toString(), e);
        }
    }
    r.setState(ON_STOP);---------------------------------------->保存状态值

    if (shouldSaveState && !isPreP) {
        callActivityOnSaveInstanceState(r);
    }
}

总结

1:pause发生在目标Activity启动之前,stop发生在目标Activity启动之后

2:被调方式不同,pause是ams有意调用的,stop则是无意调用的。onStop不一定会回调,取决于其是否可见

上一篇下一篇

猜你喜欢

热点阅读