首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从源码解析Android应用启动全流程:从点击图标到Activity渲染的深度剖析

从源码解析Android应用启动全流程:从点击图标到Activity渲染的深度剖析

原创
作者头像
李林LiLin
发布2025-07-19 14:54:24
发布2025-07-19 14:54:24
8850
举报
文章被收录于专栏:Android进阶编程Android进阶编程

本文将深入Android源码(基于Android 12),解析从用户点击桌面图标到应用完全启动的全过程,揭示系统服务、Zygote进程、Binder通信等核心机制如何协同工作。

一、起点:Launcher发起启动请求

当用户点击应用图标时,Launcher作为系统桌面应用,通过startActivity()启动目标应用:

代码语言:txt
复制
// packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
    // ...
    startActivity(intent, optsBundle);
}

这里的Intent包含关键信息:component = com.example.app/.MainActivity

二、穿越进程边界:向系统服务发起请求

Launcher通过Binder IPC调用ActivityTaskManagerService(ATMS):

代码语言:txt
复制
// frameworks/base/core/java/android/app/Activity.java
public void startActivity(Intent intent) {
    mInstrumentation.execStartActivity(
        this, mMainThread.getApplicationThread(), 
        intent, -1 /* requestCode */);
}

// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(...) {
    int result = ActivityTaskManager.getService().startActivity(...);
}

ActivityTaskManager.getService()返回的是ATMS的Binder代理对象。

三、系统进程的调度枢纽:ActivityTaskManagerService

ATMS在系统进程(system_server)中处理请求:

代码语言:txt
复制
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public final int startActivity(...) {
    return startActivityAsUser(...);
}

private int startActivityAsUser(...) {
    // 1. 验证权限
    // 2. 创建ActivityRecord
    // 3. 获取目标进程
    ProcessRecord app = mProcessMap.getProcess(...);
    if (app == null) {
        // 需要启动新进程
        mAtmInternal.startProcessAsync(...);
    }
}

关键对象创建:

  • ActivityRecord:代表一个Activity实例
  • ProcessRecord:代表应用进程状态
  • Task:管理Activity的栈

四、Zygote孵化新进程

当目标进程不存在时,ATMS通过ProcessList向Zygote发起fork请求:

代码语言:txt
复制
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
final Process.ProcessStartResult startResult = startProcess(...);

private Process.ProcessStartResult startProcess(...) {
    return Process.start(entryPoint, ...);
}

// frameworks/base/core/java/android/os/Process.java
public static ProcessStartResult start(...) {
    return zygoteProcess.start(...);
}

Zygote进程通过socket接收请求并fork:

代码语言:txt
复制
// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) {
    // ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    // 监听socket
    runSelectLoop(abiList);
}

private static void runSelectLoop() {
    // 接受AMS请求
    ZygoteConnection connection = peers.get(fdIndex);
    final Runnable command = connection.processCommand();
}

fork完成后,新进程执行ActivityThread.main()入口。

五、应用进程初始化:ActivityThread与主线程

当Zygote fork出新进程后,会执行ActivityThread.main()方法:

代码语言:txt
复制
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, ...) {
    // 通过JNI调用ZygoteInit的main方法
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
代码语言:txt
复制
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static Runnable forkAndSpecialize(...) {
    int pid = Zygote.forkAndSpecialize(...);
    if (pid == 0) {
        // 在子进程中执行
        return handleChildProc(parsedArgs, ...);
    }
}

private static Runnable handleChildProc(String[] args, ...) {
    // 最终调用ActivityThread的main方法
    return ZygoteInit.zygoteInit(...);
}

static Runnable zygoteInit(...) {
    RuntimeInit.commonInit();
    return RuntimeInit.applicationInit(...);
}

protected static Runnable applicationInit(...) {
    // 通过反射调用ActivityThread.main()
    return findStaticMain(args.startClass, args.startArgs);
}

执行流程

  • Zygote通过fork()创建新进程
  • 子进程执行handleChildProc()
  • 通过RuntimeInit.applicationInit()反射调用
  • 最终执行ActivityThread.main()

新进程从ActivityThread.main()开始执行:

代码语言:txt
复制
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    Looper.prepareMainLooper(); // 创建主线程Looper
    
    ActivityThread thread = new ActivityThread();
    thread.attach(false); // 关键:连接系统服务
    
    Looper.loop(); // 启动消息循环
}

attach()方法建立与AMS的连接:

代码语言:txt
复制
private void attach(boolean system) {
    final IActivityManager mgr = ActivityManager.getService();
    mgr.attachApplication(mAppThread); // mAppThread是ApplicationThread对象
}

此处通过Binder调用ATMS的attachApplication()

六、双向通信桥梁:ApplicationThread

ApplicationThread是ActivityThread的内部类,作为ATMS回调应用进程的Binder接口:

代码语言:txt
复制
final ApplicationThread mAppThread = new ApplicationThread();

// ActivityThread内部类
private class ApplicationThread extends IApplicationThread.Stub {
    public final void bindApplication(...) {
        sendMessage(H.BIND_APPLICATION, data);
    }
    
    public final void scheduleLaunchActivity(...) {
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
}

应用进程使用H(Handler)处理消息:

代码语言:txt
复制
class H extends Handler {
    public void handleMessage(Message msg) {
        case BIND_APPLICATION:
            handleBindApplication(data);
        case LAUNCH_ACTIVITY:
            handleLaunchActivity(r);
    }
}

七、应用级初始化:创建Application

handleBindApplication()触发应用级初始化:

代码语言:txt
复制
// frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
    // 1. 创建LoadedApk(代表加载的APK)
    final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
        appContext.getClassLoader(), false, true, false);
    
    // 2. 创建ContextImpl
    final ContextImpl appContext = ContextImpl.createAppContext(this, pi);
    
    // 3. 实例化Application
    Application app = pi.makeApplication(forceDefaultAppClass, instr);
    
    // 4. 安装ContentProviders
    if (!data.restrictedBackupMode) {
        installContentProviders(app, data.providers);
    }
    
    // 5. 回调Application.onCreate()
    mInstrumentation.callApplicationOnCreate(app);
}

关键步骤:

  1. 通过ClassLoader加载APK资源
  2. 创建应用级上下文
  3. 反射实例化自定义Application类
  4. 触发应用初始化回调

Application.attachBaseContext()何时调用?

在创建Application实例后立即调用:

代码语言:txt
复制
// frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass, 
                                   Instrumentation instrumentation) {
    // 1. 创建Application实例
    Application app = mActivityThread.mInstrumentation.newApplication(
        cl, appClass, appContext);
    
    return app;
}

// frameworks/base/core/java/android/app/Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context) {
    Application app = getFactory(context).instantiateApplication(cl, className);
    // 关键调用
    app.attach(context);
    return app;
}

// frameworks/base/core/java/android/app/Application.java
final void attach(Context context) {
    attachBaseContext(context);  // 调用Application的protected方法
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

八、Activity实例化与生命周期

收到LAUNCH_ACTIVITY消息后,创建目标Activity:

代码语言:txt
复制
// frameworks/base/core/java/android/app/ActivityThread.java
private Activity handleLaunchActivity(ActivityClientRecord r) {
    final Activity a = performLaunchActivity(r, null);
    return a;
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 1. 创建Activity实例
    Activity activity = mInstrumentation.newActivity(
        cl, component.getClassName(), r.intent);
    
    // 2. 创建Application(如果尚未创建)
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
    // 3. 关联Context
    Context appContext = createBaseContextForActivity(r, activity);
    activity.attach(appContext, ...);
    
    // 4. 回调onCreate()
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    return activity;
}

九、全流程关键节点时序图

十、关键技术点解析

1、Zygote预加载机制

  • 共享库:/system/framework/android.jar
  • 资源:预加载res/values等公共资源
  • 类:850+个预加载类(通过preload-classes配置)

2、Binder线程池管理

代码语言:txt
复制
// ProcessState.cpp初始化时
mThreadPoolStarted = true
spawnPooledThread(true) // 启动首个Binder线程

3、资源隔离机制

  • 每个应用进程持有独立的AssetManager
  • 通过ResourcesKey实现资源分区
  • 资源覆盖(Overlay)通过AssetManager.addOverlayPath()实现

4、类加载优化

代码语言:txt
复制
// LoadedApk.java
public ClassLoader getClassLoader() {
    if (mClassLoader == null) {
        mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
            zip, libPath, parent, isBundledApp);
    }
}

5、ApplicationThread的Binder本质

代码语言:txt
复制
// IApplicationThread.aidl
interface IApplicationThread {
    void bindApplication(...);
    void scheduleLaunchActivity(...);
    // 共40+个系统回调接口
}

6、attachBaseContext的特殊性

  • 唯一在Application构造函数后立即执行的方法
  • 此时ContentProvider已初始化完成
  • 但其他组件(Activity/Service)尚未创建

7、ContentProvider的初始化陷阱

代码语言:txt
复制
// 错误示例:在Application中初始化依赖ContentProvider的数据
public class MyApp extends Application {
    public void onCreate() {
        super.onCreate();
        // 此时userProvider可能未初始化完成!
        User user = userProvider.getCurrentUser(); 
    }
}
  • 解决方案:使用ContentResolver惰性查询

8、Activity创建的多阶段attach

代码语言:txt
复制
// Activity.java
final void attach(Context context, ...) {
    attachBaseContext(context); // 1. 关联上下文
    mWindow = new PhoneWindow(this); // 2. 创建窗口
    mUiThread = Thread.currentThread(); // 3. 绑定UI线程
    // 4. 关联WindowManager
    mWindow.setWindowManager(wm, ...);
}

十一、性能优化实践

1、启动阶段组件初始化优化

代码语言:txt
复制
// 优化ContentProvider初始化
<provider
    android:name=".MyProvider"
    android:authorities="com.example.provider"
    android:initOrder="100" /> <!-- 调整初始化顺序 -->

2、Multidex处理的正确位置

代码语言:txt
复制
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // 必须在此处初始化Multidex
    MultiDex.install(this);
}

3、延迟初始化策略

代码语言:txt
复制
// 使用延迟加载占位
public void onCreate() {
    getMainExecutor().execute(() -> {
        // 延迟初始化非关键组件
        initHeavyLibrary();
    });
}

4、冷启动耗时分解

代码语言:txt
复制
# 使用adb分析
adb shell am start -W -S com.example.app/.MainActivity
  • TotalTime:包括Zygote fork+初始化+Activity渲染
  • WaitTime:包含系统调度延迟

十二、总结:Android应用启动的哲学

Android应用启动流程体现了以下设计思想:

  • 进程隔离:通过Zygote fork保证进程间资源隔离
  • 异步通信:基于Binder和Handler实现跨进程协作
  • 统一生命周期:通过系统服务集中管理组件状态
  • 资源分层:系统资源与应用资源分离加载
  • 懒加载机制:按需创建组件(如BroadcastReceiver)

理解这些底层机制,不仅能优化应用启动性能,更能帮助开发者设计出符合Android设计哲学的应用程序架构。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、起点:Launcher发起启动请求
  • 二、穿越进程边界:向系统服务发起请求
  • 三、系统进程的调度枢纽:ActivityTaskManagerService
  • 四、Zygote孵化新进程
  • 五、应用进程初始化:ActivityThread与主线程
  • 六、双向通信桥梁:ApplicationThread
  • 七、应用级初始化:创建Application
  • 八、Activity实例化与生命周期
  • 九、全流程关键节点时序图
  • 十、关键技术点解析
    • 1、Zygote预加载机制
    • 2、Binder线程池管理
    • 3、资源隔离机制
    • 4、类加载优化
    • 5、ApplicationThread的Binder本质
    • 6、attachBaseContext的特殊性
    • 7、ContentProvider的初始化陷阱
    • 8、Activity创建的多阶段attach
  • 十一、性能优化实践
    • 1、启动阶段组件初始化优化
    • 2、Multidex处理的正确位置
    • 3、延迟初始化策略
    • 4、冷启动耗时分解
  • 十二、总结:Android应用启动的哲学
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档