【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)

简介: 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)

文章目录

前言

一、热启动与冷启动选择

二、AMS 进程中执行的相关操作

三、通过 Binder 机制转到 ActivityThread 中执行的操作

总结

前言

上一篇博客 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 ) 分析的分支是启动 Activity 时 , 没有 Activity 对应的进程 , 需要先调用 Zygote 启动相应进程 , 然后再启动 Activity , 属于冷启动 ;


本篇博客补充下 " 热启动 " 的流程 ;






一、热启动与冷启动选择


在 ActivityStackSupervisor.startSpecificActivityLocked 方法中 , 判定要启动的 Activity 是否存在 , 决定要使用冷启动还是热启动 ;



如果启动时 , 发现已经存在 Activity 对应进程 , 那么执行下面的热启动方法 :


 

// 如果启动 Activity 时 , 发现进程存在 , 则直接启动 Activity , 热启动
                realStartActivityLocked(r, app, andResume, checkConfig);


如果启动时 , 发现不存在 Activity 对应进程 , 那么执行下面的冷启动方法 :


// 如果启动 Activity 时 , 发现进程不存在 , 则启动进程, 然后再启动 Activity , 冷启动 
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);



ActivityStackSupervisor.startSpecificActivityLocked 方法代码 :


public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
        RecentTasks.Callbacks {
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 此活动的应用程序是否已在运行?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        getLaunchTimeTracker().setLaunchTime(r);
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // 如果它是一个标记为在多个进程中运行的平台组件,请不要添加此项,
                    // 因为它实际上是框架的一部分,因此在进程中作为单独的apk进行跟踪没有意义。
                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
                            mService.mProcessStats);
                }
    // 如果启动 Activity 时 , 发现进程存在 , 则直接启动 Activity , 热启动
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
            // 如果抛出了死对象异常,则通过fall-through重新启动应用程序。
        }
  // 如果启动 Activity 时 , 发现进程不存在 , 则启动进程, 然后再启动 Activity , 冷启动 
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
}


完整代码参考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;






二、AMS 进程中执行的相关操作


在 ActivityStackSupervisor.realStartActivityLocked 启动 Activity ;


最终调用 mService.getLifecycleManager().scheduleTransaction(clientTransaction) 方法 , 启动相关 Activity 启动事物 ;



ActivityStackSupervisor.realStartActivityLocked 相关代码如下 :
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
        RecentTasks.Callbacks {
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {
        if (!allPausedActivitiesComplete()) {
            // 当有活动暂停时,我们将跳过开始任何新活动,直到暂停完成。
            // 注意:对于在暂停状态下启动的活动,我们也会这样做,因为它们将首先恢复,然后在客户端暂停。
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "realStartActivityLocked: Skipping start of r=" + r
                            + " some activities pausing...");
            return false;
        }
        final TaskRecord task = r.getTask();
        final ActivityStack stack = task.getStack();
        beginDeferResume();
        try {
            r.startFreezingScreenLocked(app, 0);
            // 安排启动时间以收集有关慢速应用程序的信息。
            r.startLaunchTickingLocked();
            r.setProcess(app);
            if (getKeyguardController().isKeyguardLocked()) {
                r.notifyUnknownVisibilityLaunched();
            }
            // 让窗口管理器根据新的活动顺序重新评估屏幕方向。
            // 注意,这样做的结果是,它可以使用新的方向调用activity manager。
            // 我们不关心这一点,因为活动当前未运行,所以我们只是重新启动它。
            if (checkConfig) {
                // 推迟恢复,因为我们将很快启动新活动。
                // 我们不希望在确保配置和尝试恢复重点堆栈的顶级活动的同时,重复启动同一记录。
                ensureVisibilityAndConfig(r, r.getDisplayId(),
                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
            }
            if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
                    true /* isTop */)) {
                // 仅当基于keyguard状态允许活动可见时,我们才将可见性设置为true。
                // 这样可以避免在窗口管理器中将此设置为运动状态,
                // 而由于以后的调用而取消该设置,以确保将可见性设置回false的可见活动。
                r.setVisibility(true);
            }
            try {
                // 下面的代码是启动 Activity 的核心代码
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));
                // 设置所需的最终状态。配置生命周期
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    // 开启新的 Activity
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    // 终止 Activity
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // 安排事务。
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                // 上面的代码是启动 Activity 的核心代码
            } catch (RemoteException e) {
            }
        } finally {
            endDeferResume();
        }
        return true;
    }
}


完整代码参考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;


目录
相关文章
|
17天前
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
90 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
4月前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
107 1
|
4月前
线程CPU异常定位分析
【10月更文挑战第3天】 开发过程中会出现一些CPU异常升高的问题,想要定位到具体的位置就需要一系列的分析,记录一些分析手段。
114 0
|
2月前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
82 4
|
2月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
3月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
4月前
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
111 6
|
4月前
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
41 3
|
4月前
|
缓存 前端开发 Android开发
Android实战之如何截取Activity或者Fragment的内容?
本文首发于公众号“AntDream”,介绍了如何在Android中截取Activity或Fragment的屏幕内容并保存为图片。包括截取整个Activity、特定控件或区域的方法,以及处理包含RecyclerView的复杂情况。
41 3
|
4月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
92 4