【Android 源码分析】Activity生命周期之onDestroy

news2024/11/17 9:45:16

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
                  
                  
                                           – 服装学院的IT男

本篇已收录于Activity短暂的一生系列
欢迎一起学习讨论Android应用开发或者WMS
V:WJB6995
Q:707409815

正文

生命周期系列:

  • Activity生命周期之onPause

  • onCreate,onStart,onResume-1

  • onCreate,onStart,onResume-2

  • Activity生命周期之onStop-1

  • Activity生命周期之onStop-2

  • Activity生命周期之onDestory

生命周期分析系列剩下最后一个 onDestroy 了,但是之前分析的桌面冷启动案例没有 onDestroy 这一步,所以写了个App, 有2个 Activity ,操作为:
MainActivity 启动 MainActivity2 ,然后按back键,这样就会触发 MainActivity2 的 onDestroy。

对应的Events日志如下:

// MainActivity2 触发 finish (writeWmFinishActivity)
04-02 19:11:46.665 13550 18317 I wm_finish_activity: [0,105165904,12,com.example.myapplication/.MainActivity2,app-request]
//  MainActivity2 触发 pause
04-02 19:11:46.671 13550 18317 I wm_pause_activity: [0,105165904,com.example.myapplication/.MainActivity2,userLeaving=false,finish]
//  MainActivity2 应用端执行生命周期onPause
04-02 19:11:46.680 19818 19818 I wm_on_paused_called: [105165904,com.example.myapplication.MainActivity2,performPause]
//  MainActivity2 添加到stop计划
04-02 19:11:46.681 13550 18317 I wm_add_to_stopping: [0,105165904,com.example.myapplication/.MainActivity2,completeFinishing]
04-02 19:11:46.687 13550 18317 I wm_set_resumed_activity: [0,com.example.myapplication/.MainActivity,resumeTopActivity]
04-02 19:11:46.700 13550 18317 I wm_resume_activity: [0,183091121,12,com.example.myapplication/.MainActivity]
04-02 19:11:46.713 19818 19818 I wm_on_restart_called: [183091121,com.example.myapplication.MainActivity,performRestartActivity]
04-02 19:11:46.714 19818 19818 I wm_on_start_called: [183091121,com.example.myapplication.MainActivity,handleStartActivity]
04-02 19:11:46.715 19818 19818 I wm_on_resume_called: [183091121,com.example.myapplication.MainActivity,RESUME_ACTIVITY]
04-02 19:11:46.715 19818 19818 I wm_on_top_resumed_gained_called: [183091121,com.example.myapplication.MainActivity,topWhenResuming]
// MainActivity2 触发 destroy
04-02 19:11:47.092 13550 13571 I wm_destroy_activity: [0,105165904,12,com.example.myapplication/.MainActivity2,finish-imm:idle]
// MainActivity2 执行 onStop
04-02 19:11:47.128 19818 19818 I wm_on_stop_called: [105165904,com.example.myapplication.MainActivity2,LIFECYCLER_STOP_ACTIVITY]
// MainActivity2 执行 onDestroy
04-02 19:11:47.130 19818 19818 I wm_on_destroy_called: [105165904,com.example.myapplication.MainActivity2,performDestroy]

现在开始消消乐

04-03 15:02:41.806 31569 31732 D AutofillManagerService: onBackKeyPressed()
04-03 15:02:41.808 31569 32057 V WindowManager: Finishing activity r=ActivityRecord{6dbc456 u0 com.example.myapplication/.MainActivity2} t8}, result=0, data=null, reason=app-request
04-03 15:02:41.808 31569 32057 I wm_finish_activity: [0,115065942,8,com.example.myapplication/.MainActivity2,app-request]

1. 应用端触发finish – wm_finish_activity

按back键是会触发 Activity::finish 方法的,所以从这里开始跟流程

# Activity
    public void finish() {
        finish(DONT_FINISH_TASK_WITH_ACTIVITY);
    }
    private void finish(int finishTask) {
        ......
            
            if (ActivityClient.getInstance().finishActivity(mToken, resultCode, resultData,
                    finishTask)) {
                mFinished = true;
            }
        ......
    }

# ActivityClient
    public boolean finishActivity(IBinder token, int resultCode, Intent resultData,
            int finishTask) {
        try {
            return getActivityClientController().finishActivity(token, resultCode, resultData,
                    finishTask);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

然后就要开始跨进程交给 SystemService 端处理了

2. SystemService 端处理

# ActivityClientController
    /**
     * This is the internal entry point for handling Activity.finish().
     *
     * @param token      The Binder token referencing the Activity we want to finish.
     * @param resultCode Result code, if any, from this Activity.
     * @param resultData Result data (Intent), if any, from this Activity.
     * @param finishTask Whether to finish the task associated with this Activity.
     * @return Returns true if the activity successfully finished, or false if it is still running.
     */
    @Override
    public boolean finishActivity(IBinder token, int resultCode, Intent resultData,
            int finishTask) {
            ......
            final long origId = Binder.clearCallingIdentity();
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity");
            try {
                ......
                // 主流程
                r.finishIfPossible(resultCode, resultData, resultGrants,
                            "app-request", true /* oomAdj */);
                res = r.finishing;
                ......
            } finally {
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                Binder.restoreCallingIdentity(origId);
            }
            ......
    }   
# ActivityRecord
    @FinishRequest int finishIfPossible(int resultCode, Intent resultData,
            NeededUriGrants resultGrants, String reason, boolean oomAdj) {
        // log 
        ProtoLog.v(WM_DEBUG_STATES, "Finishing activity r=%s, result=%d, data=%s, "
                + "reason=%s", this, resultCode, resultData, reason);
        ......
        try {
            mTaskSupervisor.mNoHistoryActivities.remove(this);
            // 重点* 1. 设置为正在 finish 
            makeFinishingLocked();
            // Make a local reference to its task since this.task could be set to null once this
            // activity is destroyed and detached from task.
            final Task task = getTask();
            // 重点* 2. 第一个events :wm_finish_activity
            EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
                    task.mTaskId, shortComponentName, reason);
            ......
            // 重点* 3. 返回Result
            finishActivityResults(resultCode, resultData, resultGrants);
            ......
            // Tell window manager to prepare for this one to be removed.
            / 重点* 4.设置不可见
            setVisibility(false);
            if (getTaskFragment().getPausingActivity() == null) {
                // 重点* 5. 打印2个log
                ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);
                if (DEBUG_USER_LEAVING) {
                    Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
                }
                // 重点* 6.开始执行pause逻辑
                getTaskFragment().startPausing(false /* userLeaving */, false /* uiSleeping */,
                            null /* resuming */, "finish");
                ......
            }
            ......
        } finally {
            mAtmService.continueWindowLayout();
        }
    }
    1. 设置当前 Activity 正在 finish (ActivityRecord下的变量finishing为true)
    1. 这里打印了第1个 MainActivity2 的 events 日志:wm_finish_activity
    1. ActivityResults 相关,当前不关心
    1. 设置 Activity 不可见
    1. 这里有2个日志打印,都表示在处理 finish 之前需要先执行 pause(那下一步肯定是触发 pause)
    1. 开始执行 MainActivity2 的 pause

2.1 makeFinishingLocked

# ActivityRecord
    void makeFinishingLocked() {

        if (finishing) {
            return;
        }
        // 表示当前Activity正在执行finish流程
        finishing = true;
        ......
    }

这里 finishing 还是挺重要的, 后面判断是否要 destory 这个 Activity 就会用到这个变量。

2.2 开始执行pause流程 – wm_pause_activity

pause 流程之前已经看过了,这边直接执行了 TaskFragment::startPausing ,那下一步肯定就是直接调用 TaskFragment::schedulePauseActivity 然后构建执行 PauseActivityItem 了

# TaskFragment

    void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
            boolean pauseImmediately, String reason) {
        // Proto日志
        ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
        try {
            // 重点* 1. 输出events 日志 wm_pause_activity
            EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                    prev.shortComponentName, "userLeaving=" + userLeaving, reason);
            // 重点* 2. 构建并执行PauseActivityItem
            mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                    prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately));
        } catch (Exception e) {
            ......
        }
    }
    1. 打印第2个 MainActivity2 的events 日志: wm_pause_activity
    1. 构建执行 PauseActivityItem 事务

2.3 addToStopping 流程 – wm_add_to_stopping

下一步的 events 日志为:wm_add_to_stopping 也就是 MainActivity2 的 addToStopping 流程。

这个之前在【Activity生命周期之onStop】分析过,可能场景不同逻辑不完全一致,但是核心逻辑都是一样的,就不再跟了,

肯定是将 MainActivity2 添加到 ActivityTaskSupervisor 下的 mStoppingActivities 集合。

再下面的就是 MainActivity 的一些生命周期处理,当前也不是分析重点。

2.4 触发销毁 – wm_destroy_activity

整个 events 日志里没有 wm_stop_activity 而是换成了 wm_destroy_activity ,但是有 wm_on_stop_called 和 wm_on_destroy_called 说明会执行 onStop 和onDestroy。

这个是符合我已知信息的,但是没有 wm_stop_activity 让我有点意外,那说明没有构建 StopActivityItem ,也就是说 onStop 可能是那个在 TransactionExecutorHelper::getLifecyclePath 触发的,这个方法会打log,在日志中确实搜到了这段log:

 D TransactionExecutor: tId:-185591831 Cycle activity: .MainActivity2 from: ON_PAUSE to: ON_DESTROY excludeLastState: true

wm_destroy_activity 日志打印的方法在 ActivityRecord::destroyImmediately 方法,加上堆栈后得到以下信息

04-08 11:18:26.452 12717 12883 E biubiubiu:   destroyImmediately: ActivityRecord{630bcae u0 com.example.myapplication/.MainActivity2} t12 f}}
04-08 11:18:26.452 12717 12883 E biubiubiu: java.lang.Exception
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityRecord.destroyImmediately(ActivityRecord.java:3732)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityRecord.destroyIfPossible(ActivityRecord.java:3675)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityTaskSupervisor.processStoppingAndFinishingActivities(ActivityTaskSupervisor.java:1959)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityTaskSupervisor.activityIdleInternal(ActivityTaskSupervisor.java:1403)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityTaskSupervisor$ActivityTaskSupervisorHandler.activityIdleFromMessage(ActivityTaskSupervisor.java:2426)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityTaskSupervisor$ActivityTaskSupervisorHandler.handleMessageInner(ActivityTaskSupervisor.java:2459)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.wm.ActivityTaskSupervisor$ActivityTaskSupervisorHandler.handleMessage(ActivityTaskSupervisor.java:2401)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at android.os.Handler.dispatchMessage(Handler.java:106)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at android.os.Looper.loopOnce(Looper.java:210)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at android.os.Looper.loop(Looper.java:297)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at android.os.HandlerThread.run(HandlerThread.java:67)
04-08 11:18:26.452 12717 12883 E biubiubiu: 	at com.android.server.ServiceThread.run(ServiceThread.java:44)

可以看到是熟悉的 ActivityTaskSupervisor::processStoppingAndFinishingActivities 方法触发的。
看一下代码:

# ActivityTaskSupervisor

    /**
     * Processes the activities to be stopped or destroyed. This should be called when the resumed
     * 处理要停止或销毁的Activity。这应该在resumed时调用
     * activities are idle or drawn.
     */
    private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
            boolean processPausingActivities, String reason) {
                // 准备要执行 Stop 的Activity 集合 
                ArrayList<ActivityRecord> readyToStopActivities = null;
                // 重点 * 1. 遍历mStoppingActivities
                for (int i = mStoppingActivities.size() - 1; i >= 0; --i) {
                    // 获取到ActivityRecord (当前分析场景就1个)
                    final ActivityRecord s = mStoppingActivities.get(i);
                    final boolean animating = s.isAnimating(TRANSITION | PARENTS,
                            ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)
                            || s.inTransition();
                    // 日志
                    ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
                            + "finishing=%s", s, s.nowVisible, animating, s.finishing);
                    // 条件满足才执行
                    if (!animating || mService.mShuttingDown) {
                        ......
                        // 打印 准备stop的log
                        ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
                        if (readyToStopActivities == null) {
                            readyToStopActivities = new ArrayList<>();
                        }
                        // 重点 * 2. 添加进集合
                        readyToStopActivities.add(s);
                        // 从集合中移除
                        mStoppingActivities.remove(i);
                    }
                }
                // 重点 * 3. 遍历readyToStopActivities
                final int numReadyStops = readyToStopActivities == null ? 0 : readyToStopActivities.size();
                for (int i = 0; i < numReadyStops; i++) {
                    final ActivityRecord r = readyToStopActivities.get(i);
                    // 4. 检查该ActivityRecord对象是否在历史记录中。  
                    if (r.isInHistory()) {
                        // 如果该ActivityRecord对象正在结束(可能是用户或系统触发的结束操作)。
                        if (r.finishing) {
                            // TODO(b/137329632): Wait for idle of the right activity, not just any.
                            // 重点* 4.1 尝试执行destroy  (finish流程)
                            r.destroyIfPossible(reason);
                        } else {
                            // 重点* 4.2 尝试停止它 (stop流程)
                            r.stopIfPossible();
                        }
                    }
                }
                ......
            }

这个方法在分析 stop 流程已经看过了,区别在于最后执行的逻辑不同,因为在前面介绍 SystemService 端处理finish 时,开始就会执行 ActivityRecord::finishIfPossible ,然后触发
ActivityRecord::makeFinishingLocked 将 finishing 设置为true, 表示这个Activity 正在执行 finish 流程,所以在执行到这个方法时,就会直接走 ActivityRecord::destroyIfPossible

这里就是finish 和 stop 的区别

# ActivityRecord
    boolean destroyIfPossible(String reason) {
        // 1. 设置状态为 FINISHING
        setState(FINISHING, "destroyIfPossible");
        // Make sure the record is cleaned out of other places.
        // 2. 从需要stop的集合中移除
        mTaskSupervisor.mStoppingActivities.remove(this);
        ......
        // 3. 设置 finishing = true
        makeFinishingLocked();
        // 4. 尝试立即销毁(正常返回false)
        final boolean activityRemoved = destroyImmediately("finish-imm:" + reason);
        ......
        ProtoLog.d(WM_DEBUG_CONTAINERS, "destroyIfPossible: r=%s destroy returned "
                + "removed=%s", this, activityRemoved);

        return activityRemoved;
    }
    1. 这里将 ActivityRecord 的状态设置为 FINISHING
    1. 从stop列表中移除
    1. 设置 finishing = true (不过当前场景 finishing 已经为true了)
    1. 执行 destroyImmediately 方法处理后续流程
# ActivityRecord
    boolean destroyImmediately(String reason) {
        ......
        // 如果状态正在处于 destory 则return
        if (isState(DESTROYING, DESTROYED)) {
            ProtoLog.v(WM_DEBUG_STATES, "activity %s already destroying, skipping "
                    + "request with reason:%s", this, reason);
            return false;
        }
        // events 日志:wm_destroy_activity  
        EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
            task.mTaskId, shortComponentName, reason);
        ......

            // log
            if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
            // 构建执行 Destroy 事务
            mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), token,
                    DestroyActivityItem.obtain(finishing, configChangeFlags));
        ......
    }
    1. 打印了 events 日志:wm_destroy_activity
    1. 构建执行DestroyActivityItem (注意这里第一个参数,当前场景为true)

那后续的逻辑就又到应用端处理了,服务端整理的堆栈如下:

ActivityTaskSupervisorHandler::handleMessage
    ActivityTaskSupervisorHandler::handleMessageInner   -- IDLE_NOW_MSG
        ActivityTaskSupervisor$ActivityTaskSupervisorHandler::activityIdleFromMessage
            ActivityTaskSupervisor::activityIdleInternal
                ActivityTaskSupervisor::processStoppingAndFinishingActivities
                    ActivityRecord::destroyIfPossible
                        ActivityRecord::destroyImmediately
                                ActivityRecord::setState  FINISHING
                                ActivityRecord::makeFinishingLocked
                                ActivityRecord::destroyImmediately 构建执行 DestroyActivityItem 

3. 应用端处理处理finish – wm_on_stop_called, wm_on_destroy_called

DestroyActivityItem 的定义如下:

# DestroyActivityItem

    private boolean mFinished;

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
        // 执行下一步,第二个参数为mFinished
        client.handleDestroyActivity(r, mFinished, mConfigChanges,
                false /* getNonConfigInstance */, "DestroyActivityItem");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    @Override
    public int getTargetState() {
        return ON_DESTROY;
    }
    
    public static DestroyActivityItem obtain(boolean finished, int configChanges) {
        DestroyActivityItem instance = ObjectPool.obtain(DestroyActivityItem.class);
        if (instance == null) {
            instance = new DestroyActivityItem();
        }
        // 复制给mFinished
        instance.mFinished = finished;
        instance.mConfigChanges = configChanges;

        return instance;
    }

3.1 onStop – wm_on_stop_called

前面说过这个流程的onStop 是通过 TransactionExecutorHelper::getLifecyclePath 方法触发的,执行时机在触发 DestroyActivityItem::execute 之前。
如果对这点有疑问的参考 【Activity生命周期之onCreate,onStart,onResume】的Activity 生命周期事务跨进程处理方式详解
onStop 流程也在 【onStop】讲过了。

最终会输出 events日志:wm_on_stop_called 并执行 Activity 的onStop

当然日志的打印顺序能更直观的证明

在这里插入图片描述

3.2 onDestroy – wm_on_destroy_called

根据 DestroyActivityItem::execute 的定义直接看 ActivityThread::handleDestroyActivity 方法

# ActivityThread
    @Override
    public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
            boolean getNonConfigInstance, String reason) {
        // 1. 主流程 onDestroy
        performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
        // 2. 视图相关处理
        cleanUpPendingRemoveWindows(r, finishing);
        WindowManager wm = r.activity.getWindowManager();
        View v = r.activity.mDecor;
        if (v != null) {
            if (r.activity.mVisibleFromServer) {
                mNumVisibleActivities--;
            }
            IBinder wtoken = v.getWindowToken();
            if (r.activity.mWindowAdded) {
                if (r.mPreserveWindow) {
                    // ......需要保留Window
                } else {
                    ......
                     // 立即移除当前视图 (触发WindowManagerGlobal移除)
                    wm.removeViewImmediate(v);
                }
            }
            if (wtoken != null && r.mPendingRemoveWindow == null) {
                // 后续会触发 ViewRootImpl::doDie 移除View
                WindowManagerGlobal.getInstance().closeAll(wtoken,
                        r.activity.getClass().getName(), "Activity");
            } else if (r.mPendingRemoveWindow != null) {
                ......
            }
            r.activity.mDecor = null;
        }
        ......

        if (finishing) {
            // 3. 通知 SystemService 端
            ActivityClient.getInstance().activityDestroyed(r.token);
        }
        mSomeActivitiesChanged = true;
    }

做了三件事:

    1. 执行到 Activity 的 onDestroy
    1. 处理UI相关的移除
    1. 通知 SystemService 端这个 Activity 已经 Destroy 了,后续该干啥干啥

3.2.1 onDestroy 流程

# ActivityThread
    void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {

                Class<? extends Activity> activityClass = null;
                // 日志
                if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
                // 拿到 Activity
                activityClass = r.activity.getClass();
                        r.activity.mConfigChangeFlags |= configChanges;
                //  当前场景finishing 为true
                if (finishing) {
                    r.activity.mFinished = true;
                }
                // 如果需要则执行pause逻辑
                performPauseActivityIfNeeded(r, "destroy");
                // 如果还没stop, 则需要执行stop逻辑
                if (!r.stopped) {
                    callActivityOnStop(r, false /* saveState */, "destroy");
                }
                ......
                try {
                    r.activity.mCalled = false;
                    // * 主流程
                    mInstrumentation.callActivityOnDestroy(r.activity);
                    ......
                } ......
                // 设置ActivityClientRecord状态-- ON_DESTROY
                r.setState(ON_DESTROY);
                // 发送消息 PURGE_RESOURCES
                schedulePurgeIdler();
                ......
            }

个人感觉比较重要的地方都加了注释,然后继续看主流程

# Instrumentation
    public void callActivityOnDestroy(Activity activity) {
        activity.performDestroy();
    }
# Activity
    final void performDestroy() {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performDestroy:"
                    + mComponent.getClassName());
        }
        dispatchActivityPreDestroyed();
        mDestroyed = true;
        // 设置Window 下 mDestroyed 为true
        mWindow.destroy();
        mFragments.dispatchDestroy();
        // 重点* 执行onDestroy
        onDestroy();
        // wm_on_destroy_called
        EventLogTags.writeWmOnDestroyCalled(mIdent, getComponentName().getClassName(),
                "performDestroy");
        ......
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
    }

流程结束!

3.2.2 UI处理

相关的代码都在注释里加上了,创建 Activity 的时候也有一些 UI 的处理,当前 finish 自然也有对应的处理,不过不是当前主要分析的逻辑。
后续会出一篇专门介绍 创建和销毁 Activity 时 UI 的一些处理。

3.3 总结 – 调用链整理

应用端处理的调用链如下:

ActivityThread::handleDestroyActivity
    ActivityThread::performDestroyActivity       -- onDestroy流程
        Instrumentation::callActivityOnDestroy
            Activity::performDestroy
                Activity::onDestroy
    WindowManagerImpl::removeViewImmediate        -- UI处理
        WindowManagerGlobal::removeView
    ActivityClient::activityDestroyed            -- SystemService 进程处理

4 SystemService 进程处理 – activityDestroyed

应用端已经执行完 Destroy 流程了,自然也要通知到 SystemService 进程做对应的后续处理 。

# ActivityClient
    public void activityDestroyed(IBinder token) {
        try {
            getActivityClientController().activityDestroyed(token);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }
# ActivityClientController
    @Override
    public void activityDestroyed(IBinder token) {
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
        final long origId = Binder.clearCallingIdentity();
        synchronized (mGlobalLock) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed");
            try {
                final ActivityRecord r = ActivityRecord.forTokenLocked(token);
                if (r != null) {
                    // 重点* 执行 destroyed
                    r.destroyed("activityDestroyed");
                }
            } finally {
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

这里有一些log和加了Trace, 但是重点就是执行了 ActivityRecord::destroyed 方法

# ActivityRecord
    /**
    * 此方法仅应在Activity被销毁且完成时,由客户端通过Binder调用
    */
    void destroyed(String reason) {
        // 移除销毁超时定时器
        removeDestroyTimeout();
        // 日志
        ProtoLog.d(WM_DEBUG_CONTAINERS, "activityDestroyedLocked: r=%s", this);

        // 检查状态
        if (!isState(DESTROYING, DESTROYED)) {

            // 不符合预期,抛出异常
            throw new IllegalStateException(
                    "Reported destroyed for activity that is not destroying: r=" + this);

        }
        // 如果Activity位于RootTask
        if (isInRootTaskLocked()) {
            // 清理服务
            cleanUp(true /* cleanServices */, false /* setState */);

            // 从历史记录中移除该Activity,并传递销毁原因
            removeFromHistory(reason);
        }

        // 重点* 通知根窗口容器恢复焦点任务的顶层Activity
        mRootWindowContainer.resumeFocusedTasksTopActivities();

}

重点就是在最后执行了 RootWindowContainer::resumeFocusedTasksTopActivities .
因为已经有一个 Activity 执行完了finish 流程,那界面上面显示的 Activity 当然会有一些变化,所以执行一些这个流程,来确保屏幕内容的正常显示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

命令行操作的基本指令【Linux】学完使用操作命令行就像喝汤一样快

致谢:Linux常用命令大全(手册) – 真正好用的Linux命令在线查询网站 提供的命令查询 一、认识操作系统 1.1计算机层级结构 操作系统是一款进行软硬件资源管理的软件 计算机从最接近我们的开始是软件->操作系统->设备驱动->硬件,我们学习软件要学习他的使用方法,而…

【光伏混合储能】VSG并网运行,构网型变流器,虚拟同步机仿真

摘要 本文提出了一种基于光伏发电与混合储能系统结合的虚拟同步发电机&#xff08;VSG&#xff09;控制策略&#xff0c;该策略能够在并网运行时稳定电网电压和频率。通过仿真分析&#xff0c;验证了该策略在各种运行工况下的有效性&#xff0c;展示了其在电力系统中的广泛应用…

RDI ADCP命令与ASCII输出结构

RDI ADCP命令与ASCII输出结构 一、RDI垂直式ADCP:1.1固定命令&#xff1a;1.2 向导命令 二、RDI水平式ADCP三、ADCP 公共目录四、常用BBTalk命令五、ADCP的ASCII输出数据文件、流量与数据结构5.1 ASCII类输出&#xff1a;5.2 ASCII 输出数据文件头5.3 ASCII 输出数据集5.4 导航…

PMP--三模--解题--91-100

文章目录 10.沟通管理--沟通管理计划--沟通管理计划是项目管理计划的组成部分&#xff0c;描述将如何规划&#xff0c;结构化、执行与监督项目沟通&#xff0c;以提高沟通的有效性。该计划包括如下信息&#xff1a;干系人的沟通需求。--与干系人沟通的文件&#xff0c;要看沟通…

Prometheus监控MySQL主从数据库

案例分析Prometheus监控MySQL主从数据库 1. 规划节点 节点规划&#xff0c;见表1。 表1 节点规划 IP主机名节点192.168.100.3masterPrometheus Grafana192.168.100.3mastermysql/master mysqld_exporter node_exporter192.168.100.4nodemysql/master mysqld_exporter …

毕业设计选题:基于ssm+vue+uniapp的家庭记账本小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

开放式耳机的优缺点?哪个品牌专业?好用的开放式蓝牙耳机分享

我相信很多想入手的开放式耳机的家人都想知道开放式耳机是什么&#xff0c;开放式耳机有什么优缺点&#xff0c;开放式耳机是不是智商税、值不值得购买以及如果要购买的话&#xff0c;有什么专业的开放式耳机品牌推荐。因为我毕竟是测评过三十多款开放式耳机的数码博主&#xf…

67.【C语言】枚举类型

1.定义 对于有限的情况,一一列举 如一周有7天,从周一到周日;光学三原色(Red Green Blue) 2.格式 enum 枚举类型名 {//枚举常量 }; 备注:enum为enumeration缩写 3.枚举成员变量的值 #include <stdio.h> enum color {Red,Green,Blue };int main() {printf("%d…

健康信息管理:SpringBoot的创新应用

第2章相关技术 2.1 B/S架构 B/S结构的特点也非常多&#xff0c;例如在很多浏览器中都可以做出信号请求。并且可以适当的减轻用户的工作量&#xff0c;通过对客户端安装或者是配置少量的运行软件就能够逐步减少用户的工作量&#xff0c;这些功能的操作主要是由服务器来进行控制的…

C++平台跳跃游戏

目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件 程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #include <iostream> #include "Player.h" using namespace std; void printma…

【环保背景高管1009】2022顶刊论文数据,环保背景高管对投资的影响探究

今天给大家分享的是国内顶刊数量经济技术经济研究2022年发布的名为《高管环保背景与绿色投资者进入》论文使用到的数据——高管环保背景数据以及管理自主权的高管环保背景数据&#xff0c;该文章利用中国上市公司沪深A股2007-2017年的面板数据&#xff0c;采用双向固定效应模型…

YOLOv11改进 | 独家创新- 注意力篇 | YOLOv11结合全新多尺度线性注意力机制MLAttention(全网独家创新)

1. MLAttention介绍 (1). 多尺度卷积操作&#xff1a;MLAttention通过多尺度卷积操作来增强不同尺度的特征表达能力。采用了多种卷积核尺寸&#xff08;例如5x5、1x7、7x1、1x11、11x1、1x21、21x1&#xff09;的深度可分离卷积来捕捉不同感受野的特征。较小的卷积核擅长捕捉细…

四,MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)

四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用) 文章目录 四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)1. 主键策略1.1 主键生成策略介绍 2. 准备工作&#xff1a;2.1 AUTO 策略2.2 INPUT 策略2.3 ASSIGN_ID 策略2.3.1 雪花算…

基础算法之双指针--Java实现(下)--LeetCode题解:有效三角形的个数-查找总价格为目标值的两个商品-三数之和-四数之和

这里是Themberfue 今天继续讲解经典算法 > 双指针算法 没看过上篇文章的小伙伴记得去看看哦&#x1f618; 有效三角形的个数 题目链接&#xff1a;有效三角形的个数 题目解析 题目要求在该数组中任意选取三个数&#xff0c;看这三个数是否可以构成可以一个有效三角形。最后…

2024上半年网络安全漏洞态势报告

2024年9月26日&#xff0c;“2024中国数字经济创新发展大会”在汕头成功召开&#xff0c;大会汇聚业界精英&#xff0c;旨在全面探讨在新形势新挑战下&#xff0c;如何“健全数据安全体系 构建可信流通环境”。在《数据安全与合规发展专题》分论坛上&#xff0c;工业和信息化部…

Windows远程Kylin系统-xrdp

Windows远程Kylin系统-xrdp 一. 查看开放端口 查看是否有3389端口二. 安装xrdp Kylin对应的是centos8 下载链接&#xff1a;https://rhel.pkgs.org/8/epel-x86_64/xrdp-0.10.1-1.el8.x86_64.rpm.html rpm -Uvh 包名 systemctl start xrdp 启动服务 systemctl enable xrdp …

只出现一次的数字|||(考察点为位操作符)

目录 一题目&#xff1a; 二思路汇总&#xff1a; 三代码解答&#xff1a; 一题目&#xff1a; leetcode原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二思路汇总&#xff1a; 思路&#xff1a;如果直接对数组按位异或&#xff0c;那么最后得到的是a^b&a…

pnpm install的时候失败提示python问题

忘记是哪个依赖了&#xff0c;npm正常&#xff0c;pnpm的时候就异常&#xff0c;但是报错里python异常 解决方法&#xff1a;安装python就行 ennn免安装的python好麻烦 网上找教程安装python好麻烦&#xff0c;发现微软可以直接安装&#xff0c;就用微软的安装了 查看结果 p…

数字化转型新时代:TOGAF框架助力企业颠覆式创新

1. 从传统到未来&#xff1a;TOGAF如何驱动企业的数字化转型 在传统业务模式面临挑战的时代&#xff0c;TOGAF&#xff08;The Open Group Architecture Framework&#xff09;提供了帮助企业完成从传统到数字化业务模式转型的强大工具。通过系统化的架构开发方法&#xff08;…

JSP(Java Server Pages)基础使用三(表单传参)

表单传参 1.这次学习的是我们在网络上使用次数相对来说很多的jsp的使用方式&#xff0c;表单传参是运用了form表单的post方法来讲表单中的数据传递给action页面,action的作用是跳转就类似a标签&#xff0c;当然action不只可以是页面&#xff0c;还可以是后端类&#xff0c;用来…