Activity启动流程(十)栈顶Activity执行onStop
发布日期:2021-07-23 22:22:32 浏览次数:1 分类:技术文章

本文共 22827 字,大约阅读时间需要 76 分钟。

在ActivityThread的handleResumeActivity中,最后一行

一:从handleResumeActivity到Idler

@Override    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,            String reason) {        // If we are getting ready to gc after going to the background, well        // we are back active so skip it.        unscheduleGcIdler();        mSomeActivitiesChanged = true;        // TODO Push resumeArgs into the activity for consideration        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);        if (r == null) {            // We didn't actually resume the activity, so skipping any follow-up actions.            return;        }        final Activity a = r.activity;        if (localLOGV) {            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);        }        final int forwardBit = isForward                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;        // If the window hasn't yet been added to the window manager,        // and this guy didn't finish itself or start another activity,        // then go ahead and add the window.        boolean willBeVisible = !a.mStartedActivity;        if (!willBeVisible) {            try {                willBeVisible = ActivityManager.getService().willActivityBeVisible(                        a.getActivityToken());            } catch (RemoteException e) {                throw e.rethrowFromSystemServer();            }        }        if (r.window == null && !a.mFinished && willBeVisible) {            r.window = r.activity.getWindow();            View decor = r.window.getDecorView();            decor.setVisibility(View.INVISIBLE);            ViewManager wm = a.getWindowManager();            WindowManager.LayoutParams l = r.window.getAttributes();            a.mDecor = decor;            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;            l.softInputMode |= forwardBit;            if (r.mPreserveWindow) {                a.mWindowAdded = true;                r.mPreserveWindow = false;                // Normally the ViewRoot sets up callbacks with the Activity                // in addView->ViewRootImpl#setView. If we are instead reusing                // the decor view we have to notify the view root that the                // callbacks may have changed.                ViewRootImpl impl = decor.getViewRootImpl();                if (impl != null) {                    impl.notifyChildRebuilt();                }            }            if (a.mVisibleFromClient) {                if (!a.mWindowAdded) {                    a.mWindowAdded = true;                    wm.addView(decor, l);                } else {                    // The activity will get a callback for this {@link LayoutParams} change                    // earlier. However, at that time the decor will not be set (this is set                    // in this method), so no action will be taken. This call ensures the                    // callback occurs with the decor set.                    a.onWindowAttributesChanged(l);                }            }            // If the window has already been added, but during resume            // we started another activity, then don't yet make the            // window visible.        } else if (!willBeVisible) {            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");            r.hideForNow = true;        }        // Get rid of anything left hanging around.        cleanUpPendingRemoveWindows(r, false /* force */);        // The window is now visible if it has been added, we are not        // simply finishing, and we are not starting another activity.        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {            if (r.newConfig != null) {                performConfigurationChangedForActivity(r, r.newConfig);                if (DEBUG_CONFIGURATION) {                    Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "                            + r.activity.mCurrentConfig);                }                r.newConfig = null;            }            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.myQueue().addIdleHandler(new Idler());

看下Idler这个类

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;                IActivityManager am = ActivityManager.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);                            a.createdConfig = null;                        } catch (RemoteException ex) {                            throw ex.rethrowFromSystemServer();                        }                    }                    prev = a;                    a = a.nextIdle;                    prev.nextIdle = null;                } while (a != null);            }            if (stopProfiling) {                mProfiler.stopProfiling();            }            ensureJitEnabled();            return false;        }    }

二 到远端activityIdle

点am.activityIdle ,这个其实在ActivityManagerService中

@Override    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {        final long origId = Binder.clearCallingIdentity();        synchronized (this) {            ActivityStack stack = ActivityRecord.getStackLocked(token);            if (stack != null) {                ActivityRecord r =                        mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,                                false /* processPausingActivities */, config);                if (stopProfiling) {                    if ((mProfileProc == r.app) && mProfilerInfo != null) {                        clearProfilerLocked();                    }                }            }        }        Binder.restoreCallingIdentity(origId);    }

 

三 ActivityStackSupervisor 的 activityIdleInternalLocked

// Checked.    @GuardedBy("mService")    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,            boolean processPausingActivities, Configuration config) {        if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);        ArrayList
finishes = null; ArrayList
startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forTokenLocked(token); 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, -1, -1); } // 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); if (isFocusedStack(r.getStack()) || fromTimeout) { booting = checkFinishBootingLocked(); } } if (allResumedActivitiesIdle()) { if (r != null) { mService.scheduleAppGcsLocked(); } if (mLaunchingActivity.isHeld()) { mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) { throw new IllegalStateException("Calling must be system uid"); } mLaunchingActivity.release(); } ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } // Atomically retrieve all of the other things to do. final ArrayList
stops = processStoppingActivitiesLocked(r, true /* remove */, processPausingActivities); 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.getStack(); if (stack != null) { if (r.finishing) { stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false, "activityIdleInternalLocked"); } else { stack.stopActivityLocked(r); } } } // 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); final ActivityStack stack = r.getStack(); 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.mUserController.finishUserSwitch(startingUsers.get(i)); } } } mService.trimApplications(); //dump(); //mWindowManager.dump(); if (activityRemoved) { resumeFocusedStackTopActivityLocked(); } return r; }

四:ActivityStack 的stopActivityLocked

final void stopActivityLocked(ActivityRecord r) {        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);        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.app != null && r.app.thread != null) {            adjustFocusedActivityStack(r, "stopActivity");            r.resumeKeyDispatchingLocked();            try {                r.stopped = false;                if (DEBUG_STATES) Slog.v(TAG_STATES,                        "Moving to STOPPING: " + r + " (stop requested)");                r.setState(STOPPING, "stopActivityLocked");                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,                        "Stopping visible=" + r.visible + " for " + r);                if (!r.visible) {                    r.setVisible(false);                }                EventLogTags.writeAmStopActivity(                        r.userId, System.identityHashCode(r), r.shortComponentName);                mService.getLifecycleManager().scheduleTransaction(r.app.thread, 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");                }            }        }    }

五:StopActivityItem

mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,

                        StopActivityItem.obtain(r.visible, r.configChangeFlags));

这样有来到了一个item,StopActivityItem

看下StopActivityItem的execute方法

@Override    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");        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);    }

最终还是调到了远端的handleStopActivity方法。

六:ActivityThread的handleStopActivity方法

@Override    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);        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;    }

performStopActivityInner

/**     * Core implementation of stopping an activity.  Note this is a little     * tricky because the server's meaning of stop is slightly different     * than our client -- for the server, stop means to save state and give     * it the result when it is done, but the window may still be visible.     * For the client, we want to call onStop()/onStart() to indicate when     * the activity's UI visibility changes.     * @param r Target activity client record.     * @param info Action that will report activity stop to server.     * @param keepShown Flag indicating whether the activity is still shown.     * @param saveState Flag indicating whether the activity state should be saved.     * @param finalStateRequest Flag indicating if this call is handling final lifecycle state     *                          request for a transaction.     * @param reason Reason for performing this operation.     */    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) {                    // 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);            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);            }        }    }

callActivityOnstop

/**     * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates     * the client record's state.     * All calls to stop an activity must be done through this method to make sure that     * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.     */    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(false /*preserveWindow*/, reason);        } 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);        }    }

进入activity的performStop

final void performStop(boolean preserveWindow, String reason) {        mDoReportFullyDrawn = false;        mFragments.doLoaderStop(mChangingConfigurations /*retain*/);        // Disallow entering picture-in-picture after the activity has been stopped        mCanEnterPictureInPicture = false;        if (!mStopped) {            if (mWindow != null) {                mWindow.closeAllPanels();            }            // If we're preserving the window, don't setStoppedState to true, since we            // need the window started immediately again. Stopping the window will            // destroys hardware resources and causes flicker.            if (!preserveWindow && mToken != null && mParent == null) {                WindowManagerGlobal.getInstance().setStoppedState(mToken, true);            }            mFragments.dispatchStop();            mCalled = false;            mInstrumentation.callActivityOnStop(this);            writeEventLog(LOG_AM_ON_STOP_CALLED, reason);            if (!mCalled) {                throw new SuperNotCalledException(                    "Activity " + mComponent.toShortString() +                    " did not call through to super.onStop()");            }            synchronized (mManagedCursors) {                final int N = mManagedCursors.size();                for (int i=0; i

 mInstrumentation.callActivityOnStop(this);

/**     * Perform calling of an activity's {@link Activity#onStop}     * method.  The default implementation simply calls through to that method.     *      * @param activity The activity being stopped.     */    public void callActivityOnStop(Activity activity) {        activity.onStop();    }

最终终于调用到了activity的onStop方法。。

=====================================================

Activity启动流程终于过完了.......好复杂。。。

转载地址:https://blog.csdn.net/perfectnihil/article/details/91049474 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:关于 ActivityRecord
下一篇:Activity启动流程(九)onStart到onResume Activity启动完毕

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年03月26日 22时27分04秒