android 四大组件—Activity源码详解
onCreate
ActivityThread.handleLaunchActivity
/*** ActivityThread 收到 AMS 的 LAUNCH_ACTIVITY 事务后进入的入口。* 负责把 ActivityClientRecord 真正变成可交互的 Activity 对象并启动其生命周期。** @param r 封装了 AMS 要启动的 Activity 全部信息(Intent、package、config 等)* @param pendingActions 来自 AMS 的“后续待办”列表(如是否调用 onPostCreate、是否 report 空闲等)* @param customIntent 可选,AMS 侧再次修正的 Intent(优先级高于 r.intent)* @return 已经走完 onCreate 的 Activity 实例;若启动失败返回 null*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions,Intent customIntent) {// 真正创建 Activity 实例、创建 PhoneWindow、attach 基类、调用 onCreate 等final Activity a = performLaunchActivity(r, customIntent);// 此处省略后续代码:// 1. 设置 pendingActions 标记位// 2. 执行 onStart、onPostCreate、reportSizeConfigurations 等// 3. 通知 AMS 进入 RESUMED 状态// 4. 触发 IdleHandler、内存压力统计return a;
}
ActivityThread.performLaunchActivity
/*** 把 AMS 传来的“要启动的 Activity” 真正变成 Java 对象并走完 onCreate 生命周期。* 返回已初始化完成的 Activity 实例;若失败返回 null。*/
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {Activity activity = null;/* ---------- 1. 反射创建 Activity 对象 ---------- */try {java.lang.ClassLoader cl = appContext.getClassLoader();// 通过 Instrumentation 反射调用无参构造,实例化 Activityactivity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);} catch (Exception e) {// 异常会抛回 AMS,应用崩溃...}/* ---------- 2. 建立 Activity 与系统侧的关联 ---------- */// 把新生成的 Activity 塞进 ContextImpl,实现 getBaseContext()appContext.setOuterContext(activity);// attach 给 Activity 注入 PhoneWindow、主线程 Handler、Token、配置等// 这一步之后 Activity 才有 Window 可用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, window, r.activityConfigCallback,r.assistToken, r.shareableActivityToken);/* ---------- 3. 执行生命周期 onCreate ---------- */if (r.isPersistable()) {// 支持持久化存储的场景(API 21+)mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {// 普通场景mInstrumentation.callActivityOnCreate(activity, r.state);}return activity; // 回到 handleLaunchActivity,继续走 onStart、onResume
}
Activit.attach
在attach的时候创建了PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
attach() 时 PhoneWindow 先创建好 mDecor 空壳
Activit.setContentView ->PhoneWindow.setContentView
public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar();}
PhoneWindow.setContentView
/*** Activity/Dialog 的入口方法:把 layoutResID 对应的 XML 填充成真正可见的 View 树。* 首次调用时负责初始化 DecorView;同时把DecorView和PhoneWindow绑定* mDecor.setWindow(this);支持过渡动画(FEATURE_CONTENT_TRANSITIONS)。*/
public void setContentView(int layoutResID) {/* 1. 还没有 DecorView 就创建一个(含 TitleBar/ActionBar/状态栏背景等系统区域) */if (mContentParent == null) {installDecor(); // 生成 DecorView,并给 mContentParent 赋值} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {/* 2. 普通模式:先清掉旧内容,避免重复添加 */mContentParent.removeAllViews();}/* 3. 判断是否启用“内容过渡动画”(Transition) */if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {/* 3.1 用 Scene/TransitionManager 做切换动画(API 19+) */final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext());transitionTo(newScene); // 旧 Scene → 新 Scene,自动执行过渡} else {/* 3.2 普通模式:直接把 XML inflate 到 mContentParent */mLayoutInflater.inflate(layoutResID, mContentParent);}/* 4. 通知 View 树重新计算 WindowInsets(状态栏/导航栏边距) */mContentParent.requestApplyInsets();/* 5. 回调告知 Activity/Dialog:内容已更换(供主题、ActionBar 等做后续调整) */final Callback cb = getCallback();if (cb != null && !isDestroyed()) {cb.onContentChanged();}/* 6. 标记:开发者已主动调用过 setContentView,后续某些逻辑可跳过默认填充 */mContentParentExplicitlySet = true;
}
onResume
ActivityThread.handleResumeActivity
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {//执行activity的onResume,如果在这里添加messge,消息是先于加入wms的performTraversals,所有获取不到view的高度
//handleResumeActivity() → performResumeActivity() → Activity.performResume() → Instrumentation.callActivityOnResume() → Activity.onResume()if (!performResumeActivity(r, finalStateRequest, reason)) {return;
}// 条件:Activity 还没把窗口真正添加进 WMS
// 1. r.window == null : 之前没有创建 PhoneWindow(第一次 resume)
// 2. !a.mFinished : Activity 没有被 finish
// 3. willBeVisible : 系统认为接下来需要可见
if (r.window == null && !a.mFinished && willBeVisible) {// 1. 从 Activity 中拿到 PhoneWindow;第一次 resume 时这里才真正拿到引用r.window = r.activity.getWindow();// 2. 取出 DecorView(此时已经 inflate 完成)View decor = r.window.getDecorView();// 先设为 INVISIBLE,等真正 ready 时再显示,避免闪屏decor.setVisibility(View.INVISIBLE);// 3. 准备 WindowManager(其实就是 Activity 内部的 WindowManagerImpl)ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();// 4. 缓存到 ActivityClientRecord,方便后续直接访问a.mDecor = decor;/* ===== 设置窗口属性 ===== */l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; // 普通应用窗口l.softInputMode |= forwardBit; // 保留/叠加软键盘模式标志/* ===== 复用窗口的特殊处理 ===== */// r.mPreserveWindow = true 表示“热启动”场景:Activity 重建但 DecorView 复用if (r.mPreserveWindow) {a.mWindowAdded = true; // 标记为“已添加”r.mPreserveWindow = false;// 通知 ViewRootImpl:Activity 回调(比如 onAttachedToWindow)可能已经变化ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}/* ===== 真正把 DecorView 添加到 WMS ===== */if (a.mVisibleFromClient) { // 客户端希望可见if (!a.mWindowAdded) { // 尚未 addViewa.mWindowAdded = true;wm.addView(decor, l); // 真正向 WMS 添加窗口} else {// 已经 addView 过,但 LayoutParams 可能变化// 触发一次 onWindowAttributesChanged 让 Activity 有机会处理a.onWindowAttributesChanged(l);}}// 如果窗口已添加,但在 resume 过程中又启动了别的 Activity,// 则暂时保持 INVISIBLE,由后续逻辑决定何时真正显示。
}
ActivityThread.performResumeActivity
/*** 在 ActivityThread 中把指定 Activity 推进到 ** resumed ** 状态的核心方法。* 会被 handleResumeActivity() 调用,完成 onResume 生命周期并注册跟踪。** @param r 要恢复的 Activity 记录(token、Activity 实例、配置等)* @param finalStateRequest 是否来自 AMS 的最终状态请求(true 表示必须走到 resumed)* @param reason 触发原因字符串(如 "handleResumeActivity" 或 "activityIdle"),用于日志/调试* @return 如果 Activity 正常走完 onResume 返回 true;若中途销毁则返回 false*/
public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,String reason) {/* 1. 先检查状态:确保 Activity 尚未被 finish 或销毁 */r.activity.onStateNotSaved(); // 清除“已保存状态”标记,允许 Fragment 事务提交/* 2. 真正调用生命周期:onRestart → onStart → onResume */r.activity.performResume(r.startsNotResumed, reason);// 内部流程:// · 若处于 stopped 状态,先走 onRestart() → onStart()// · 无论之前状态,都走 onResume()// · 通知 Fragment 进入 RESUMED// · 设置 mResumed = true// · 向 AMS 报告 idle(若需要)/* 3. 后续在 handleResumeActivity 还会:* - 把 DecorView 添加到 WindowManager* - 设置可见性 View.VISIBLE* - 注册接收按键、触摸事件*/return true; // 若未抛异常即视为成功
}
Activity.performResume
mInstrumentation.callActivityOnResume(this);
Instrumentation.callActivityOnResume
public void callActivityOnResume(Activity activity) {activity.mResumed = true;activity.onResume();if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);am.match(activity, activity, activity.getIntent());}}}
}