Android中级——Activity数据恢复过程
Activity数据恢复
- onSaveInstanceState()
- onRestoreInstanceState()
- 扩展
onSaveInstanceState()
在Activity调用onStop()之前调用会onSaveInstanceState(),如下
final void performStopActivity(IBinder token, boolean saveState, String reason) {ActivityClientRecord r = mActivities.get(token);performStopActivityInner(r, null /* stopInfo */, saveState, false /* finalStateRequest */,reason);
}private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean saveState, boolean finalStateRequest, String reason) {......callActivityOnStop(r, saveState, reason);......
}private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {......final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null && !r.isPreHoneycomb();final boolean isPreP = r.isPreP();if (shouldSaveState && isPreP) {callActivityOnSaveInstanceState(r);}try {r.activity.performStop(r.mPreserveWindow, reason);}......
}
onSaveInstanceState()存储Window视图树、调用Fragment、ActivityLifecycleCallbacks的onSaveInstanceState()
protected void onSaveInstanceState(@NonNull Bundle outState) {outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);Parcelable p = mFragments.saveAllState();if (p != null) {outState.putParcelable(FRAGMENTS_TAG, p);}if (mAutoFillResetNeeded) {outState.putBoolean(AUTOFILL_RESET_NEEDED, true);getAutofillManager().onSaveInstanceState(outState);}dispatchActivitySaveInstanceState(outState);
}
上面调用到PhoneWindow的saveHierarchyState()
@Override
public Bundle saveHierarchyState() {Bundle outState = new Bundle();if (mContentParent == null) {return outState;}SparseArray<Parcelable> states = new SparseArray<Parcelable>();mContentParent.saveHierarchyState(states); outState.putSparseParcelableArray(VIEWS_TAG, states); //存储视图树的结构final View focusedView = mContentParent.findFocus();if (focusedView != null && focusedView.getId() != View.NO_ID) {outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); //存储当前焦点所在View的ID,持有焦点的View必须设置ID,否则无法恢复}SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();savePanelState(panelStates);if (panelStates.size() > 0) {outState.putSparseParcelableArray(PANELS_TAG, panelStates); //存储面板信息}if (mDecorContentParent != null) {SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();mDecorContentParent.saveToolbarHierarchyState(actionBarStates);outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates); //存储actionBar}return outState;
}
mContentParent即是Activity中setContentView()所设置的根布局,调用到View的saveHierarchyState()方法
public void saveHierarchyState(SparseArray<Parcelable> container) {dispatchSaveInstanceState(container);
}
若当前是ViewGroup,则遍历child调用其dispatchSaveInstanceState()
@Override
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {super.dispatchSaveInstanceState(container);final int count = mChildrenCount;final View[] children = mChildren;for (int i = 0; i < count; i++) {View c = children[i];if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {c.dispatchSaveInstanceState(container);}}
}
若当前是View,则从onSaveInstanceState()获取state根据当前View的ID保存到SparseArray
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;Parcelable state = onSaveInstanceState();......if (state != null) {......container.put(mID, state);}}
}
onSaveInstanceState()需要由子类自身去实现,以TextView为例,保存了字符串、间距、位置信息等
@Override
public Parcelable onSaveInstanceState() {Parcelable superState = super.onSaveInstanceState();final boolean freezesText = getFreezesText();boolean hasSelection = false;int start = -1;int end = -1;if (mText != null) {start = getSelectionStart();end = getSelectionEnd();if (start >= 0 || end >= 0) {hasSelection = true;}}if (freezesText || hasSelection) {SavedState ss = new SavedState(superState);if (freezesText) {if (mText instanceof Spanned) {final Spannable sp = new SpannableStringBuilder(mText);if (mEditor != null) {removeMisspelledSpans(sp);sp.removeSpan(mEditor.mSuggestionRangeSpan);}ss.text = sp;} else {ss.text = mText.toString();}}if (hasSelection) {ss.selStart = start;ss.selEnd = end;}if (isFocused() && start >= 0 && end >= 0) {ss.frozenWithFocus = true;}ss.error = getError();if (mEditor != null) {ss.editorState = mEditor.saveInstanceState();}return ss;}return superState;
}
onRestoreInstanceState()
在performLaunchActivity()中,取出ActivityClientRecord中的state传给Activity的OnCreate()方法,在正常启动时,state为空,需要对state进行判空
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {try {......if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}......r.activity = activity;} ......synchronized (mResourcesManager) {mActivities.put(r.token, r);}}......return activity;
}
在handleStartActivity()中先调用onStart(),再调用OnRestoreInstanceState()
@Override
public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {final ActivityClientRecord r = mActivities.get(token);final Activity activity = r.activity;......activity.performStart("handleStartActivity");......if (pendingActions.shouldRestoreInstanceState()) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}......
}
扩展
Activity并非每次退出都会调用onSaveInstanceState(),如当用户按Back键主动退出时,下面列举几种调用onSaveInstanceState()的情况
- 按下Home键
- 长按Home键选中运行其他程序
- 按下电源键息屏
- 从Activity启动一个新的Activity
- 屏幕方向切换
- 电话打入
相关文章:
Android中级——Activity数据恢复过程
Activity数据恢复 onSaveInstanceState()onRestoreInstanceState()扩展 onSaveInstanceState() 在Activity调用onStop()之前调用会onSaveInstanceState(),如下 final void performStopActivity(IBinder token, boolean saveState, String reason) {ActivityClient…...
国内就能使用的chatgpt网页版,包含AIGC应用工具
Chatgpt的出现在多个领域带来了重要的影响。它能够显著提高我们的工作效率,无论是编写文案代码还是回答常见问题,都能在短时间内完成任务。通过Chatgpt,我们能够迅速获取所需答案。随着人工智能技术的不断发展,相信在未来AI能够带…...
Fast DDS之RTPS
目录 RTPS的使用 RTPS层实现了RTPS标准。DDS层概念映射关系如下: DDS LayerRTPS LayerDomainRTPSDomainDomainParticipantRTPSParticipantDataWriterRTPSWriterDataReaderRTPSReader RTPS的使用...
【算法|动态规划No.16】leetcode931. 下降路径最小和
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望…...
Jenkins 构建时动态获取参数
文章目录 问题简介Groovy 脚本配置进阶 问题 在做jenkins项目时,有些参数不是固定写死的,而是动态变化的,这时我们可以用 Active Choices 插件来远程调用参数 问题解决方案:执行构建前使用Groovy Scrip调用本地脚本,…...
android app开机自启动
参考文章: Android APP开机启动,安卓APP开发自启动,安卓启动后APP自动启动 Android让程序开机自动运行APP_安卓应用开机启动并打开软件_weijia3624的博客-CSDN博客...
XSS CSRF
XSS & CSRF xss:跨站脚本攻击:注入一些非法的脚本 csrf:冒充身份 XSS 反射型 /welcome:res.send(req.query.type) 输入什么就输出什么(httpOnly:false,但不是解决方案) 比如:?&…...
新加坡星银行项目组笔试题面试题
Java/Fullstack___开发常见问题收集:(根据个人面试岗位进行参考) 项目介绍部分 介绍最近做过的项目,项目中遇到的印象深刻的问题,如何解决?就项目用到的技术,自己的技术以及如何使用࿱…...
基于SpringBoot的智能物流管理系统
目录 前言 一、技术栈 二、系统功能介绍 顾客信息管理 员工信息管理 员工信息管理 门店信息管理 门店信息管理 订单信息管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施…...
【开源电商网站】(2),使用docker-compose和dockerfile进行配置,设置自定义的镜像,安装插件,增加汉化包,支持中文界面汉化。
项目相关代代码地址 相关内容: https://blog.csdn.net/freewebsys/category_12461196.html 原文地址: https://blog.csdn.net/freewebsys/article/details/133666433 包括以下运行的详细代码: https://gitee.com/study-demo-all/oscommerc…...
HTML5开发实例-3D全景(ThreeJs全景Demo) 详解(图)
前言 在现在市面上很多全景H5的环境下,要实现全景的方式有很多,可以用css3直接构建也可以用基于threeJs的库来实现,还有很多别的制作全景的软件使用 本教学适用于未开发过3D全景的工程狮 如果觉得内容太无聊可以直接跳到最后 下载代码 理论 整个3D全景所用的相关理论就…...
springboot项目静态资源映射
1. springboot项目静态资源映射 import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import...
【Linux初阶】多线程1 | 页表的索引作用,线程基础(优缺点、异常、用途),线程VS进程,线程控制,C++多线程引入
文章目录 ☀️一、深入理解页表☀️二、Linux线程概念🌻1.什么是线程(重点)⚡(1)线程的概念⚡(2)线程库初识 🌻2.线程的优点🌻3.线程的缺点🌻4.线程异常&…...
Flink--9、双流联结(窗口联结、间隔联结)
星光下的赶路人star的个人主页 我还有改变的可能性,一想起这点,我就心潮澎湃 文章目录 1、基于时间的合流——双流联结(Join)1.1 窗口联结(Window Join)1.2 间隔联结(Interval Join)…...
家政服务行业做开发微信小程序可以实现什么功能
家政服务行业开发微信小程序可以实现多种功能,从而提升服务品质和效率,下面我们来详细介绍一些可能实现的功能。 一、展示服务信息 家政服务微信小程序可以展示各种服务信息,包括各类家政服务项目、价格、服务流程、服务人员信息等。用户可以…...
20哈希表-三数之和
目录 LeetCode之路——15. 三数之和 分析: 官方题解: LeetCode之路——15. 三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nu…...
JVM 运行时数据区和垃圾收集算法
在 《深入理解 Java 虚拟机》一书中,作者将运行时数据区和垃圾收集算法放在开头章节,说明了这两个知识点是进一步学习 JVM 的基础知识点,相比后续的 垃圾收集器和 JMM,它也更加的简单。 运行时数据区 运行时数据区是《Java 虚拟…...
Java基于SpringBoot的高校招生系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 简介系统设计思路1 数据库设计2 系统整体设计 系统详细设计1系统功能模块2. 管理员功能模块3学生…...
6. Python使用Asyncio开发TCP服务器简单案例
1. 说明 在Python中开发TCP/IP服务器有两种方式,一种使用Socket,需要在py文件中引入对应的socket包,这种方式只能执行单项任务;另一种方式使用Asyncio异步编程,可以一次创建多个服务器执行不同的任务。 2. 接口说明 …...
景联文科技:AI大模型强势赋能,助力自动驾驶迭代升级
我国一直以来都将自动驾驶作为新兴产业发展的重点领域之一,工信部等相关部委出台了一系列自动驾驶发展战略、规划和标准,一些地方政府也在积极开展关于自动驾驶的地方立法,为自动驾驶技术的研发和应用提供更加具体的法律保障。例如࿰…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
