性能优化比拼:app启动流程之冷热启动Activity的SnapshotWindow

SpringBoot项目整合达梦数据库(MYSQL 转换 达梦数据库) 注意:当迁移过程中出现下面问题时,如有触发器或者外键,需要先关掉触发器和外键,然后进行迁移,不然会导致迁移失败。(2)dm.ini修改【#compatibility】的【COMPATIBLE_MODE】=4。3、添加用户:如果导入的DM数据库需要和MYSQL的用户一样,添加ROOT用户。方法一:服务器配置:设置系统兼容性(DM控制台工具),兼容MySQL。服务器配置又该有两种方式:①DM控制台工具修改;MYSQL的数据表转换成DM的数据表时,点击转换按钮。在这里操作:MYSQL数据库迁移至DM数据库。 阅读详情

背景

前面文章有对冷启动的Splash Window进行了详细的,但是大家是否有想过稳启动时候的是否也需要有类似的Splash Window呢?
答案是肯定的,具体可以通过WinScope或者Perfetto抓取暖启动的过程来验证:

暖启动的StartingWindow

其实桌面的暖启动也会有一个StartingWindow,名字叫做SnapshotStartingWindow,他的启动时间明显比冷启动SplashWindow要快很多,几乎为SplashWindow时间的1/2,可以看到点击后,SnapshotStartingWindow在68ms后就进行了上帧。

再看看冷启动的SplashWindow的时间:

在这里插入图片描述可以看出桌面点击后,要118ms才有Splash window的绘制帧数据。

SnapshotStartingWindow数据是啥?

冷启动时候大家都知道SplashWindow数据就是ICON + 背景色的样子
在这里插入图片描述
但是暖启动时候SnapshotStartingWindow显示内容是啥呢?

实际上他显示内容就是类似最近任务一样的,是activity内容的截图
获取方式:
截图文件保存在:

  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>.jpg                                                                                                                                                       
  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>.proto                                                                                                                                                     
  /data/system_ce/<userId>/snapshots/<随机UUID>/<taskId>_reduced.jpg      
  

实战如下:

adb pull /data/system_ce/0/snapshots/09c8fa2d-ff1b-482f-882c-eb1e0b5ca51d/789.jpg
/data/system_ce/0/snapshots/09c8fa2d-ff1b-482f-882c-eb1e0b5ca51d/789.jpg: 1 file pulled, 0 skipped. 19.7 MB/s (86913 bytes in 0.004s)

在这里插入图片描述

为什么感知不到SnapshotStartingWindow存在呢?

其实感知不到SnapshotStartingWindow存在就是系统设计这个SnapshotStartingWindow成功的表现,本身就是想让你无感的点击图标后进入到Activity真实内容,但是因为Activity真实内容显示是需要一定时间的,哪怕暖启动。那么在真实Activity绘制前这段时间就需要使用SnapshotStartingWindow来显示,他显示的内容是上一次Activity退出的task截图。

感知不到SnapshotStartingWindow存在其实有2个因素:
1、SnapshotStartingWindow的显示时间非常短暂,可能是100ms左右,相比SplashWindow显示500ms时间短了很多。
在这里插入图片描述

2、SnapshotStartingWindow本身就是显示task的截图,所以内容上和Activity的真实显示内容是高度一致的,所以很难感知出他们的变化,除非画面会有大的变化才可能会有跳变感。

整体流程架构总结

system_server (ATMS/WMS)                          Shell (com.android.wm.shell)
══════════════════════════                        ═══════════════════════════════

ActivityRecord.addStartingWindow()
  │
  ├─ getStartingWindowType()
  │     │
  │     ├─ newTask/!processRunning → SPLASH
  │     └─ taskSwitch + snapshot   → SNAPSHOT  ← 温启动命中
  │
  ├─ createSnapshot()
  │     └─ new SnapshotStartingData(snapshot)
  │
  ├─ StartingSurfaceController
  │     .createTaskSnapshotSurface()
  │
  └─ TaskOrganizerController
        .addStartingWindow()                       ──Binder IPC──▶  TaskSnapshotWindow.create()
                                                                    │
                                                                    ├─ IWindowSession.addToDisplay()
                                                                    ├─ IWindowSession.relayout()
                                                                    ├─ SnapshotDrawerUtils
                                                                    │   .drawSnapshotOnSurface()
                                                                    │     └─ setBuffer(HardwareBuffer)
                                                                    └─ reportDrawn()

                    ═══════ Snapshot 显示中,App 首帧正在绘制 ═══════

ActivityRecord.onFirstWindowDrawn()
  │
  └─ removeStartingWindow()
       │
       └─ TaskOrganizerController
            .removeStartingWindow()                ──Binder IPC──▶  TaskSnapshotWindow
                                                                      .removeImmediately()
                                                                        └─ IWindowSession.remove()

在这里插入图片描述

添加路径: ActivityRecord → StartingSurfaceController → TaskOrganizerController → Binder → TaskSnapshotWindow

移除路径: ActivityRecord.onFirstWindowDrawn() → TaskOrganizerController → Binder → TaskSnapshotWindow.removeImmediately()

原文地址:
https://mp.weixin.qq.com/s/mtcG-00_KS-NyVs4bL5zEw

更多fw实战干货请关注下面“千里马学框架”

创建XCP的CanApe工程 阅读详情

相关推荐

OSMDroid 切换地图不更新的问题

用OSMDroid加载Google地图的时候 需要有按钮切换不同图层的地图,如果发现调用了mMapView.setTileSource(ITileSource aTileSource)方法的时候发现地图View没有更新的话,可能是因为两个实例化TileSource对象其子类BitmapTileSourceBase这个类的aName成员变量值一样导致的地图在setTileSource出现不更新问题,...

godoge的博客 1039

Android Visualizer 实战:把声音画出来

是系统提供的音频效果(AudioEffect)之一。它挂在音频链路上,,把数据回吐给你——画波形、画频谱、做响度表。

Android的专栏 304

Zenoh:统一数据平面协议,重塑物联网与边缘计算架构

在分布式系统与物联网领域,数据通信与处理常面临协议割裂的挑战。传统方案如MQTT、Kafka、gRPC等,分别针对发布/订阅、流处理和RPC等不同场景,导致架构复杂、集成成本高。其核心问题在于未能统一处理“运动中数据”(Data in Motion)与“静止中数据”(Data at Rest)。Zenoh协议通过创新的“Key-Value”寻址与“Selector”查询语言,将发布/订阅、存储、查询和计算四种核心操作融合进单一协议,构建了统一的抽象层。这种设计实现了极低的协议开销(仅5字节头部)和地理分布式

weixin_29597551的博客 291

Android 开发入门实践(十三):用 Intent、UiState 和 Reducer 理解 MVI 的状态更新

本文记录第141—145课对MVI架构的入门实践,通过“返回列表”功能逐步构建意图(NewsIntent)、状态(NewsUiState)与状态转换(reduce)机制。基于单向数据流,用户操作生成意图,ViewModel通过Reducer根据旧状态计算新状态,并通过StateFlow更新Compose界面。代码实现清晰分离关注点,强化了对状态管理、事件驱动与数据流的理解。

Easyhood的博客 340

TI IWR 6843 ISK 毫米波雷达开箱测试

TI IWR6843 ISK毫米波雷达上手体验,教程十分详细,对于新手很友好。

qq_57061492的博客 4038

CANoe LIN一致性测试之干扰测试Test moudle_LIN Disturbance Block

注意:相邻两个显隐性不同的bit不允许干扰,例如我同时选择bit6和bit7,相邻两个同显隐性的bit允许干扰,例如当我选择bit3和bit4,项,这里我选择ID:为0x2F(PID:0x6F)的frame。需按照具体测试规范实施干扰项,帧头和数据段都可以实现干扰。最近发现一个干扰测试模块,下面是一些具体使用方法。选择干扰项:PID的奇偶校验位(一致性测试干扰测试之手动测试。一个待测试frameD。

yuanyikangkang的博客 3412

Android Message源码阅读

本文梳理了Android Handler机制中Message的核心设计:链表结构、消息复用池(sPool)及回收机制,重点解析了异步消息与同步屏障(SyncBarrier)的协同机制。当主线程需优先处理UI绘制等高优先级任务时,系统通过postSyncBarrier插入屏障,使Looper跳过普通同步消息,优先执行标记为异步的UI渲染任务,确保帧率流畅。该机制是保障Android界面响应性的关键技术之一。

u012116089的博客 205

HighTec安装(官网免费)编译 嘎嘎详细~

安装软件最好有自己的一套安装规则,工程软件除了安装主体外还会有很多其他的东西,比如license或者还会有一些驱动,如果所有都随意安装会导致你需要卸载,或者更新软件时,有的需要将原来软件卸载干净,如果没有清晰的安装路径那真是灾难啊~请确保此目录中只有个人许可证。这样基本的配置就ok了,下面打开hightec软件检验下license是否识别到了,会让你选个工作区,建议自己建一个,要不你以后就找不到了,,,如下图拉到下面,按照要求填写信息,随便写就行,注意主要的MAC地址要填本机的物理地址,然后点击2即可。

weixin_60793044的博客 1万+

RK-RK3572-Android16- 编译打包优化-OTA整包-差分包打包

这里主要记录一下 RK3572 在Android16 上面进行OTA升级的整包和差分包制作经验的一个分享,整理知识点,方便后续自己和其它同事开发提高工作效率、直接使用。不管哪一个平台,MTK 也好、RK也好 基本上都是不同Android版本各个子系统之间还是有一点点区别的,所以有必要记录整理知识点,方便提高开发效率、生产效率。针对OTA升级问题 ,再一次说明还是要看官方提供的文档,按照文档来。

十年饮冰,难凉热血 193

Python 爬虫实战:爬取万方数据文献信息

本文介绍了基于Python爬虫技术合规获取万方数据文献信息的方法。通过分析万方数据的请求机制与反爬策略,采用requests库结合Session维持合法会话,实现了文献标题、摘要、作者等核心元数据的提取。文章详细讲解了Token验证、动态请求构造、JSON数据解析等关键技术,并提供了完整可运行代码。同时强调严格遵守《万方数据知识服务平台用户协议》,控制请求频率,仅限学术研究使用。该方案为万方数据文献信息获取提供了标准化解决方案,支持数据清洗、结构化存储及后续分析应用。

2503_91057718的博客 2138

第一章 电力电子仿真软件 PLECS简介

PLECS是瑞士Plexim公司开发的电力电子仿真软件,具有快速仿真、丰富元件库和热分析功能。软件提供单机版和嵌入MATLAB的版本,支持多平台安装且流程简单。首次运行需获取授权文件,提供60分钟演示模式。界面包含模型创建、帮助文档和元件库浏览器等功能区域,操作便捷。该软件是专业高效的电力电子系统仿真工具。

502

安卓APK下载后安装全流程:从点击下载到第一次启动,每一步的检查点

这套流程听起来繁琐,但真正需要每次都做的只有来源核对和签名校验两步,其他都是出问题时才查。养成习惯之后,能挡掉绝大多数"装了垃圾包""装完闪退"的情况。如果要省事,直接用这类会标注包名、版本号和校验信息的站点,比在搜索结果里挨个试要稳得多。

qq362196705的专栏 148

RDKit | 基于Murcko骨架聚类化合物库

化合物多样性评估 一种方法是使用合适的指纹技术将化合物矢量化并评估他们之间的距离。这种方法经常被使用,但是对于人类很难直观地理解化合物之间的距离。 基于Murcko骨架,分子大致聚集在化合物骨架中,并且每个簇中的顶部化合物都作为候选化合物。此方法非常符合人类的直觉,因此可以预期人将通过查看候选化合物列表来自动缩小化合物的范围。 Murcko骨架 Mur...

DrugOne 3768

BUUCTF-菜刀流量-MISC-学习笔记

从 1970-01-01 00:00:00 UTC 起算的秒数,——Wireshark 直接告诉你它回答的是谁;由表可知道,96帧返回了flag.rar。, 代表删除键,先删了4次,又删了1次。所以密码是:SuperMaster。解析128帧的响应,即133帧。所以这是一个标准抓包文件,用。解压压缩包拿到html代码。:选中 128 帧,展开。:128 和 131 的。能把一问一答放在一起看;是八进制(Oct)的数字。(或 TCP 层)看到。对比一下ASCii 码表。

晓梦林的博客 73

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android Laya 与 Native Bridge:页面识别、双向通信、协议设计和崩溃定位

Laya 与 Native 通信的难点不在于某个或的写法,而在于边界:页面来源是否可信、协议是否明确、线程是否正确、请求是否幂等、页面是否仍然存在、日志是否能关联一次完整请求。建立这些边界后,才能把“页面白屏”“按钮无响应”“重复消息”和“Native 崩溃”拆成可验证的层次,并沿着真实调用链找到根因。

路在脚下,幸福在手中,莫贪!!!!! 164

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

悬浮窗挡住 Android:agent 读到 0 个节点

我在做一个跑在 Android 上的 agent,叫 Andee。他没有常规主界面,也不用 Compose——整个应用就是一颗悬浮球挂在你屏幕上,点那颗球说话,他靠无障碍服务读屏幕、点按钮,替你把事办了。悬浮窗权限是他唯一「不给就完全不能用」的一项:球、字幕、设置面板、保险箱,全都是。写这篇,是因为「系统级 agent」这两天开始真往用户手机上推了。荣耀 MagicOS 11 从 11 月 6 日向 Magic V6、Magic8 系列推送,今天轮到 Magic V5、Magic7 系列;

qq_42960812的博客 213

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Harness篇|DeepSeek Harness 上手机:五条安卓移植路线与 App 内 Linux 拆解

DSH 官方没出安卓版,火的全是社区第三方移植。本文拆解真实卡点(glibc vs Bionic)、两种「App 内 Linux」的实现(PRoot 与 seccomp 容器),以及「真沙箱」的三层边界与衡量标准。

AI_Gump的博客 98

Android 开发入门实践(九):把新闻数据与页面状态交给 ViewModel

本文记录第110—117课学习成果:将页面标题、新闻列表及选中编号逐步迁移至NewsViewModel,通过ViewModelProvider获取实例并读取数据。页面调用ViewModel方法处理选择与返回,实现状态管理解耦。过程中纠正了对Activity重建机制的误解,并厘清mutableStateOf的可观察性与ViewModel对象生命周期的区别,深化了对Compose状态更新机制的理解。

Easyhood的博客 224

Android 17 全栈性能分析关键字与源码手册

FrameTimeline 找异常帧,ATrace 找阶段,thread_state 找等待类型,ftrace 找内核原因,Simpleperf 找 CPU 热点,驱动源码找最终触发条件;任何根因结论都必须回到同一对象、同一时间窗口和同一条依赖链。

weixin_43228946的博客 378

谷歌相机9.2下载(GCam 安卓通用版 安装与使用说明)

谷歌相机9.2版移植自Pixel原生相机,支持Camera2 API的Android 10+设备安装,凭借多帧合成技术在夜景、HDR+与人像模式表现优异。可提升暗光画质、优化动态范围与背景虚化效果,支持视频防抖及配置文件自定义。安装需确认机型兼容性,建议备份原相机,避免冲突。资源可通过kuake链接获取,仅限学习测试使用。

2611_96675819的博客 202

Android 开发入门实践(十):用 Kotlin 协程完成模拟加载、取消与异常处理

本文记录第118—125课对NewsApp的协程改造:从viewModelScope.launch启动协程,逐步加入delay模拟等待、suspend函数封装、withContext(Dispatchers.IO)切换线程并观察上下文恢复机制。通过日志验证withContext完成后恢复原执行上下文(非自动回主线程),纠正了初始理解偏差。引入Job管理任务,实现加载取消与重复点击防护,结合异常处理与状态管理,完成可观察、可中断的异步流程。

Easyhood的博客 407

工业智能体:从Codex/Claude到项目实战~系列文章11:Codex 批量重构老系统:激活历史 DCS/PLC 存量代码

本期提出规模化重构工业老系统(如DCS/PLC代码)的可执行方法论:通过AST静态分析量化风险,按“盘点评估→样板重构→批量迁移→回归灰度”四阶段推进;利用Codex实现模块级批量重构,并以“金标准样本”确保数值一致性;接入CI流水线实现自动化守护。强调“小步改、保语义、可回滚”,结合绞杀者模式渐进替代,实现存量代码的安全激活。来自华北理工大学段一凡的博客文章

段一凡的博客 393

Android 开发入门实践(十六):网络新闻请求、Coil 图片加载与失败重试

本文通过接入JSONPlaceholder网络接口,实现新闻数据的远程获取与解析。在Repository中使用withContext(Dispatchers.IO)进行协程挂起请求,通过JSONObject解析title、body、id字段并构建News对象。结合ViewModel与StateFlow更新页面状态,利用AsyncImage加载图片,并添加失败提示与手动重试机制。完整覆盖从网络请求、数据转换到界面更新的全流程,深化对协程调度、状态管理与图片加载的理解。

Easyhood的博客 172

mysql初阶--表的操作

本文系统讲解MySQL表的DDL操作:通过SHOW TABLES查看表,CREATE TABLE创建表(支持临时表、校验语句),DESCRIBE或SHOW CREATE TABLE查看结构,ALTER TABLE修改列名、类型、增删字段及重命名表,以及DROP TABLE删除表。强调这些操作属于数据定义语言(DDL),影响表结构而非数据本身。结合存储引擎、字符集(推荐utf8mb4)、建表规范与常见报错,为后续数据操作打下坚实基础。

2601_97033068的博客 534

Android 网络与实时通信实践:请求、上传、WebSocket、RTM 与断网调试

网络与实时通信的稳定性来自状态和边界:HTTP 成功不等于业务成功,上传完成不等于业务确认,WebSocket 连接成功不等于消息送达,客户端不重复显示也不等于服务端只执行一次。只有明确认证、协议、顺序、幂等、取消和生命周期,才能在真实项目中安全地重试、恢复和定位问题。

路在脚下,幸福在手中,莫贪!!!!! 154

C语言操作MySQL

在官网中可以查到C API的使用文档,我们可以在里面查询MySQL常用函数的使用方法。使用示例:MYSQL *mfp = mysql_init(NULL);第一个参数MYSQL是 C api 中一个非常重要的变量(mysql_init 的返回值),里面有port,dbname,charset等连接基本参数。它也包含了一个叫st_mysql_methods的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。

wairuigood的博客 120
上一篇: AI替代一切工作?AI辅助学习Framework开发经验技巧分享
下一篇: 小鹏车机竞品调研:车机分屏功能的竞品调研和实现方案
千里马学框架
博客等级 码龄6年 1万+粉丝 651原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值