自学内容网 自学内容网

Android App启动流程深度解析(一):从Activity.startActivity开始

前言

在Android应用开发中,启动流程是最基础也是最重要的机制之一。作为一名Android开发者,理解应用启动的完整流程对于性能优化、问题排查和架构设计都至关重要。本系列文章将从最上层的Activity.startActivity()方法开始,自上而下深入分析Android应用启动的完整流程。

版本说明

本文分析的代码基于Android 10(API 29)及以上版本。在Android 10中,Google对Activity管理架构进行了重大调整:

  • Android 9及之前:所有Activity相关功能由ActivityManagerService(AMS)统一管理
  • Android 10及之后:将Activity和Task管理功能拆分到新的ActivityTaskManagerService(ATMS),AMS保留其他核心功能

这个变更有以下背景:

  1. 解耦Activity管理与系统其他核心功能
  2. 为多窗口、自由形态窗口等新特性提供更好的支持
  3. 改善系统服务的模块化程度

从Activity.startActivity开始

让我们从最常见的场景出发——一个Activity启动另一个Activity。开发者最熟悉的调用方式就是startActivity()方法。

Activity.startActivity()

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

这是Activity类中最简单的startActivity重载方法。可以看到它调用了另一个重载方法,并传入了一个null的Bundle参数。

Activity.startActivity(Intent, Bundle)

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

这个方法检查是否有附加的options Bundle,然后调用startActivityForResult()方法。注意这里传入的requestCode是-1,表示我们不需要返回结果。

Activity.startActivityForResult()

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    // 检查是否有父Activity
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        // 关键调用
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
    } else {
        // 如果有父Activity,则通过父Activity启动
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

这个方法有几个关键点:

  1. 首先检查是否有父Activity,如果没有则继续流程,否则通过父Activity启动
  2. 使用InstrumentationexecStartActivity方法执行实际的启动操作
  3. 如果有返回结果,则通过ActivityThread发送结果
  4. 处理Activity过渡动画

Instrumentation.execStartActivity()

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // 获取IApplicationThread对象
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // 记录来源Activity
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        // 关键调用:通过ActivityTaskManager启动Activity
        int result = ActivityTaskManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        // 检查启动结果
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

这个方法做了以下几件事:

  1. 处理ActivityMonitor(用于测试)
  2. 准备Intent数据
  3. 通过ActivityTaskManager.getService()获取AMS的代理对象,调用startActivity方法
  4. 检查启动结果

ActivityTaskManager.getService()

public static IActivityTaskManager getService() {
    return IActivityTaskManagerSingleton.get();
}

private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
            @Override
            protected IActivityTaskManager create() {
                // 获取ActivityTaskManagerService的代理对象
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                return IActivityTaskManager.Stub.asInterface(b);
            }
        };

这里通过Binder机制获取了系统服务ActivityTaskManagerService的代理对象。ATMS是Android 10之后从AMS中拆分出来的专门管理Activity和Task的服务。

checkStartActivityResult()

public static void checkStartActivityResult(int res, Object intent) {
    switch (res) {
        case ActivityManager.START_INTENT_NOT_RESOLVED:
        case ActivityManager.START_CLASS_NOT_FOUND:
            throw new ActivityNotFoundException(
                    "Unable to find explicit activity class "
                    + ((Intent)intent).getComponent().toShortString()
                    + "; have you declared this activity in your AndroidManifest.xml?");
        case ActivityManager.START_PERMISSION_DENIED:
            throw new SecurityException("Not allowed to start activity "
                    + ((Intent)intent).getComponent().toShortString());
        // 其他错误处理...
    }
}

这个方法将ATMS返回的结果转换为相应的异常,开发者常见的"Activity未在Manifest中声明"的错误就是在这里抛出的。

流程概览

到目前为止,我们看到的调用流程如下:

  1. Activity.startActivity()
  2. Activity.startActivity(Intent, Bundle)
  3. Activity.startActivityForResult()
  4. Instrumentation.execStartActivity()
  5. ActivityTaskManager.getService().startActivity()

这个流程已经从应用进程进入了系统进程(system_server),后续的处理将在ATMS中进行。

为什么需要Instrumentation?

你可能注意到在流程中有一个Instrumentation类参与其中。Instrumentation是Android测试框架的核心部分,但它也参与正常的Activity启动流程。它的主要作用有:

  1. 提供一种监控系统与应用交互的机制
  2. 在测试中可以替换组件行为
  3. 在正常运行时作为Activity生命周期回调的中间层

小结

本文从最常用的Activity.startActivity()方法开始,逐步深入分析了Android应用启动的前半段流程。我们了解到:

  1. 启动请求最终通过Instrumentation转发到系统服务
  2. 通过Binder机制与系统服务ActivityTaskManagerService交互
  3. 基本的错误检查和处理机制

附:关键差异对比表

组件/版本Android 9及之前Android 10及之后
核心服务ActivityManagerService (AMS)ActivityTaskManagerService (ATMS)
获取服务方式ActivityManager.getService()ActivityTaskManager.getService()
管理范围包含Activity管理在内的所有功能专注Activity和Task管理
Binder接口IActivityManagerIActivityTaskManager

兼容性说明

虽然架构发生了变化,但上层API保持了兼容:

// 这两种写法在Android 10+上效果相同,但后者是推荐的新方式
startActivity(intent); // 仍然可用
ActivityTaskManager.getService().startActivity(...); // 新方式

系统通过兼容层处理了API差异,因此开发者无需修改现有代码。

为什么需要拆分ATMS?

在Android 10的架构变更中,拆分ATMS的主要考虑包括:

  1. 职责单一化

    • AMS原本承担了太多职责(内存管理、进程管理、Activity管理等)
    • 拆分后ATMS专注于Activity和Task管理
  2. 多窗口支持

    • 新的多窗口模式需要更复杂的Activity栈管理
    • 独立服务可以更灵活地实现这些功能
  3. 性能优化

    • 减少AMS的锁竞争
    • 并行处理Activity相关操作

代码路径差异

在分析启动流程时,需要注意不同版本的代码路径差异:

Android 9及之前

// 老版本通过AMS启动Activity
ActivityManager.getService().startActivity(...)

Android 10及之后

// 新版本通过ATMS启动Activity
ActivityTaskManager.getService().startActivity(...)

原文地址:https://blog.csdn.net/liuzhuo13396/article/details/148703426

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!