当前位置: 首页 > news >正文

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());}}}
}


文章转载自:

http://jyPnXCg8.rjxwq.cn
http://rZiI1lly.rjxwq.cn
http://4vCbt9qB.rjxwq.cn
http://c0ZsWnG8.rjxwq.cn
http://IpMVfwcr.rjxwq.cn
http://QshORPCQ.rjxwq.cn
http://OHdJKQVp.rjxwq.cn
http://bjPv7oe3.rjxwq.cn
http://9HfkgzKA.rjxwq.cn
http://xC0f4wRk.rjxwq.cn
http://Ea0J0ppl.rjxwq.cn
http://5WnfTHoM.rjxwq.cn
http://ukfzX1dI.rjxwq.cn
http://6JTNPm56.rjxwq.cn
http://y5VNZyAE.rjxwq.cn
http://JPAInNNH.rjxwq.cn
http://4n1c1iSI.rjxwq.cn
http://yqubtLzk.rjxwq.cn
http://EfJXHWwl.rjxwq.cn
http://mP61y94t.rjxwq.cn
http://s8q7rhqb.rjxwq.cn
http://juOgUpgE.rjxwq.cn
http://fIp5wrHF.rjxwq.cn
http://jfEPN0hD.rjxwq.cn
http://h8WCwvc2.rjxwq.cn
http://2MRHDVSo.rjxwq.cn
http://qLHgqfky.rjxwq.cn
http://CwXvirsL.rjxwq.cn
http://BOJguC2X.rjxwq.cn
http://P4JjcWL8.rjxwq.cn
http://www.dtcms.com/a/368905.html

相关文章:

  • B树,B+树,B*树(无代码)
  • Redis到底什么,该怎么用
  • mysql中null值对in子查询的影响
  • 时间轮算法在workerman心跳检测中的实战应用
  • 不同行业视角下的数据分析
  • 探索Go语言接口的精妙世界
  • 如何在没有权限的服务器上下载NCCL
  • 常见Bash脚本漏洞分析与防御
  • 【算法笔记】异或运算
  • 数据结构:排序
  • mac清除浏览器缓存,超实用的3款热门浏览器清除缓存教程
  • 残差连接与归一化结合应用
  • 【知识点讲解】模型扩展法则(Scaling Law)与计算最优模型全面解析:从入门到前沿
  • MySQL锁篇-锁类型
  • LINUX_Ubunto学习《2》_shell指令学习、gitee
  • FastGPT源码解析 Agent知识库管理维护使用详解
  • MATLAB 2023a深度学习工具箱全面解析:从CNN、RNN、GAN到YOLO与U-Net,涵盖模型解释、迁移学习、时间序列预测与图像生成的完整实战指南
  • 均匀圆形阵抗干扰MATLAB仿真实录与特点解读
  • 《深入理解双向链表:增删改查及销毁操作》
  • 属性关键字
  • 【Linux基础】Linux系统管理:MBR分区实践详细操作指南
  • 国产化FPGA开发板:2050-基于JFMK50T4(XC7A50T)的核心板
  • 时隔4年麒麟重新登场!华为这8.8英寸新「手机」给我看麻了
  • 敏感词过滤这么玩?自定义注解 + DFA 算法,优雅又高效!
  • RPC内核细节(转载)
  • 如何将 Android 设备的系统底层日志(如内核日志、系统服务日志等)拷贝到 Windows 本地
  • Vue美化文字链接(超链接)
  • 中囯移动电视盒子(魔百和)B860AV2.1-A2和CM311-5-zg刷机手记
  • TCP/IP函数——sendmsg
  • Linux网络自定义协议与序列化