1. AOSP15 Activity启动流程概览
在Android系统中,Activity作为四大组件之一,其启动流程一直是开发者需要深入理解的核心机制。AOSP15(Android Open Source Project 15)对Activity启动流程做了一些优化和改进,但整体架构仍然保持了一致性。我们先从宏观角度理解这个流程:
Activity启动主要分为两个阶段:
- 系统服务阶段:由ActivityManagerService(AMS)主导,负责进程管理和任务栈管理
- 应用进程阶段:由ActivityThread处理,完成Activity对象的创建和生命周期回调
整个过程涉及多个关键类:
- ActivityManagerService:系统级Activity管理
- ActivityStackSupervisor:Activity栈管理
- ActivityThread:应用主线程
- Instrumentation:Activity生命周期监控
- ApplicationThread:应用进程与系统服务的Binder通信接口
2. 从AMS到应用进程的调用链路
2.1 启动请求的发起
当我们需要启动一个Activity时,无论是通过Launcher点击图标还是应用内调用startActivity(),最终都会通过Binder调用到ActivityManagerService。AMS会先进行一系列检查:
// ActivityStackSupervisor.java void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // 检查目标Activity所在进程是否已存在 ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); if (app != null && app.thread != null) { try { realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { // 异常处理 } } // 进程不存在则创建新进程 mService.startProcessLocked(...); }这里有个关键设计点:Android采用按需创建进程的策略。如果目标Activity所在进程已经存在,就直接启动Activity;否则先创建进程。
2.2 跨进程通信机制
AMS通过IApplicationThread接口与应用进程通信,这是一个Binder接口:
public interface IApplicationThread extends IInterface { void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException; // 其他生命周期方法... }在应用进程侧,ActivityThread的内部类ApplicationThread实现了这个接口:
private class ApplicationThread extends ApplicationThreadNative { @Override public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { // 构造ActivityClientRecord并发送消息 ActivityClientRecord r = new ActivityClientRecord(); // 填充各种参数... sendMessage(H.LAUNCH_ACTIVITY, r); } }这里采用了消息队列机制将启动请求从Binder线程切换到主线程处理,这是Android框架的典型设计模式。
3. Activity实例化与初始化
3.1 消息处理与Activity创建
ActivityThread中的H(Handler)接收到LAUNCH_ACTIVITY消息后:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { // 初始化WindowManagerGlobal WindowManagerGlobal.initialize(); // 核心创建方法 Activity a = performLaunchActivity(r, customIntent); if (a != null) { // 处理resume状态 handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); } }performLaunchActivity()是Activity创建的核心方法,其关键步骤包括:
- 从ActivityInfo中获取组件信息
- 通过Instrumentation创建Activity实例
- 创建或获取Application对象
- 创建ContextImpl并关联到Activity
- 调用Activity的attach()方法
- 触发onCreate()生命周期回调
3.2 类加载与实例化
Activity对象的创建通过Instrumentation完成:
// Instrumentation.java public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); }这里有几个需要注意的点:
- 使用目标Activity所在APK的ClassLoader
- 通过反射调用默认构造函数
- 此时Activity还未关联Context,不能调用需要Context的方法
3.3 Application对象的创建
在创建Activity之前,需要确保Application对象已经存在:
// LoadedApk.java public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } Application app = null; String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } try { // 通过Instrumentation创建Application实例 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext); appContext.setOuterContext(app); } catch (Exception e) { // 异常处理 } // 触发Application.onCreate() if (instrumentation != null) { try { instrumentation.callApplicationOnCreate(app); } catch (Exception e) { // 异常处理 } } return app; }Application对象的生命周期比Activity更长,一个进程只有一个Application实例。
4. Activity的完整初始化过程
4.1 Context的创建与关联
每个Activity都需要一个ContextImpl实例:
// ActivityThread.java private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // 创建基础Context Context appContext = createBaseContextForActivity(r, activity); // 调用attach方法 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor); // 设置主题 int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } // 调用onCreate() mInstrumentation.callActivityOnCreate(activity, r.state); return activity; }attach()方法中完成了几个重要工作:
- 关联Window对象
- 初始化WindowManager
- 设置主题和资源系统
4.2 生命周期回调的触发
Instrumentation负责监控和触发生命周期方法:
// Instrumentation.java public void callActivityOnCreate(Activity activity, Bundle icicle) { activity.performCreate(icicle); } // Activity.java final void performCreate(Bundle icicle) { onCreate(icicle); mActivityTransitionState.readState(icicle); }这里的设计采用了模板方法模式:
- Instrumentation作为监控层
- Activity提供具体实现
- performXXX()方法确保框架必要的处理逻辑
4.3 Window的创建与关联
在Activity.attach()方法中会初始化Window相关对象:
// Activity.java final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor) { // 创建PhoneWindow实例 mWindow = new PhoneWindow(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); // 设置WindowManager mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); mWindowManager = mWindow.getWindowManager(); }Window的创建有几个关键点:
- 每个Activity对应一个PhoneWindow实例
- Window通过WindowManager与WMS通信
- Activity实现了Window.Callback接口接收窗口事件
5. 启动流程中的关键设计模式
5.1 代理模式的应用
整个启动流程中广泛使用了代理模式:
- ApplicationThreadProxy:AMS与应用进程通信的代理
- WindowManagerProxy:应用与WMS通信的代理
- IActivityManager:应用与AMS通信的代理
这种设计实现了进程间的解耦,典型代码如下:
// ActivityManagerNative.java static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ActivityManagerProxy(obj); }5.2 模板方法模式
Activity生命周期管理采用了模板方法模式:
// Activity.java final void performStart() { mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); mFragments.noteStateNotSaved(); mCalled = false; mFragments.execPendingActions(); onStart(); if (!mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onStart()"); } mFragments.dispatchStart(); mFragments.reportLoaderStart(); }这种设计确保了:
- 框架必要的处理逻辑得到执行
- 开发者可以重写生命周期方法
- 强制调用super方法保证完整性
5.3 观察者模式
Instrumentation作为观察者监控Activity生命周期:
// Instrumentation.java public void callActivityOnCreate(Activity activity, Bundle icicle) { activity.performCreate(icicle); // 可以在这里添加监控逻辑 }这种设计使得:
- 框架可以监控应用行为
- 不影响正常生命周期流程
- 支持测试框架的注入
6. 流程中的性能优化点
6.1 异步启动机制
Activity启动采用了异步消息机制:
// ActivityThread.java public final void scheduleLaunchActivity(...) { sendMessage(H.LAUNCH_ACTIVITY, r); }这种设计避免了:
- Binder线程阻塞主线程
- 保证生命周期有序执行
- 支持优先级调度
6.2 资源预加载
在Activity创建前会预加载资源:
// LoadedApk.java public Resources getResources() { if (mResources == null) { mResources = ResourcesManager.getInstance().getResources(...); } return mResources; }优化点包括:
- 资源共享减少内存占用
- 资源缓存提高访问速度
- 按需加载减轻启动负担
6.3 进程复用机制
AMS维护了进程缓存:
// ActivityManagerService.java final ProcessRecord getProcessRecordLocked(String processName, int uid) { return mProcessNames.get(processName, uid); }这种机制:
- 减少进程创建开销
- 提高Activity启动速度
- 平衡系统资源使用
7. 常见问题排查技巧
7.1 启动超时问题
Activity启动默认有10秒超时(前台Activity),如果遇到ANR可以检查:
- onCreate()中是否执行了耗时操作
- ContentProvider初始化是否阻塞
- BroadcastReceiver是否处理太慢
可以通过以下命令查看超时日志:
adb logcat | grep "ActivityManager"7.2 上下文错误使用
在Activity完全初始化前使用Context会导致问题,典型错误:
// 错误示例 public class MyActivity extends Activity { private TextView mTextView = new TextView(this); // 此时this还未完全初始化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... } }正确做法是在onCreate()之后使用Context。
7.3 主题和应用问题
如果遇到样式相关问题可以检查:
- AndroidManifest.xml中是否设置了正确主题
- 是否错误覆盖了getTheme()方法
- 资源冲突或缺失
调试方法:
// 获取当前Activity实际使用的主题 int theme = getTheme().getStyle(); Log.d("CurrentTheme", Integer.toHexString(theme));8. 高级调试技巧
8.1 生命周期跟踪
可以通过以下方式跟踪完整生命周期:
- 在Application中设置全局Instrumentation:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Instrumentation instrumentation = new Instrumentation() { @Override public void callActivityOnCreate(Activity activity, Bundle icicle) { Log.d("Lifecycle", "Creating: " + activity.getClass().getSimpleName()); super.callActivityOnCreate(activity, icicle); } // 重写其他生命周期方法... }; } }- 使用adb命令监控:
adb shell am trace-ipc start adb shell am start -n com.example/.MainActivity adb shell am trace-ipc stop8.2 性能分析
分析启动耗时可以:
- 使用TraceView:
// 在代码中插入跟踪点 Debug.startMethodTracing("activity_start"); // ... Debug.stopMethodTracing();- 使用Systrace:
python systrace.py --time=10 -o trace.html am activity8.3 跨进程调用分析
分析AMS与应用的Binder通信:
- 开启Binder日志:
adb shell service call activity 1599295570- 使用Binder调试工具:
adb shell dumpsys activity service all