Android 组件提供的状态保存(saveInstanceState)与恢复(restoreInstanceState)

Android的组件Activity中,有这样一对方法: onSaveInstanceeStateonRestoreInstanceState

这两对方法,可以让我在Activiy异常销毁时,保存状态;以及在Activity重建时,恢复状态。

比如:当我们在输入框中输入了内容,此时因为种种原因,将App退至了后台。这个处于后台的App很有可能因为内存不足、其他配置,被系统杀死。

当我们恢复这个页的时候,希望它能够保存住我们原来输入的内容。

除了,我们自己手动保存,也可以利用系统的onSaveInstanceStateonRestoreInstanceState

那么,在Android已有的系统中,是如何做的呢?

我们查阅EditText,发现它的父类TextView做了保存状态与恢复状态的处理,但是根据条件(freezesText || hasSelection)做了保存与恢复,如果只用TextView用于展示,并不会触发保存与恢复。

TextView的状态保存与恢复。

// 保存状态
@Override  
public Parcelable onSaveInstanceState() {  Parcelable superState = super.onSaveInstanceState();  // Save state if we are forced to  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) {  // Or save state if there is a selection  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) {  // XXX Should also save the current scroll position!  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;  
}// 恢复状态
@Override  
public void onRestoreInstanceState(Parcelable state) {  if (!(state instanceof SavedState)) {  super.onRestoreInstanceState(state);  return;  }  SavedState ss = (SavedState) state;  super.onRestoreInstanceState(ss.getSuperState());  // XXX restore buffer type too, as well as lots of other stuff  if (ss.text != null) {  setText(ss.text);  }  if (ss.selStart >= 0 && ss.selEnd >= 0) {  if (mSpannable != null) {  int len = mText.length();  if (ss.selStart > len || ss.selEnd > len) {  String restored = "";  if (ss.text != null) {  restored = "(restored) ";  }  Log.e(LOG_TAG, "Saved cursor position " + ss.selStart + "/" + ss.selEnd  + " out of range for " + restored + "text " + mText);  } else {  Selection.setSelection(mSpannable, ss.selStart, ss.selEnd);  if (ss.frozenWithFocus) {  createEditorIfNeeded();  mEditor.mFrozenWithFocus = true;  }  }  }  }  if (ss.error != null) {  final CharSequence error = ss.error;  // Display the error later, after the first layout pass  post(new Runnable() {  public void run() {  if (mEditor == null || !mEditor.mErrorWasChanged) {  setError(error);  }  }  });  }  if (ss.editorState != null) {  createEditorIfNeeded();  mEditor.restoreInstanceState(ss.editorState);  }  
}

onSaveInstanceState&onRestoreInstanceState的执行时机

这两个函数在什么情况下使用?比如开发者模式中开启了不保留活动、屏幕方向发生改变等原因,导致Activity(视图)被销毁或重建时,会执行。

被销毁时,执行onSaveInstanceState
重建时,执行onRestoreInstanceState

当然,这两个函数的执行也是有一些条件的,比如,View必须指定了Id,Id在整个视图(PhoneWindow)内必须唯一,如果不唯一则会在恢复状态时报错(保存时不会报错)。

在View的默认实现中,如果发现id一样,则会在恢复状态时报错。

@CallSuper  
protected void onRestoreInstanceState(Parcelable state) {  mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;  if (state != null && !(state instanceof AbsSavedState)) {  throw new IllegalArgumentException("Wrong state class, expecting View State but "  + "received " + state.getClass().toString() + " instead. This usually happens "  + "when two views of different type have the same id in the same hierarchy. "  + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "  + "other views do not use the same id.");  
}
// …… 省略剩余代码
}

我们在自定义View和使用第三方控件等情况下,需要合理处理这两个函数,否则会导致崩溃。

这里附一张InstanceState的执行时机图:

在这里插入图片描述

save的状态保存在哪里?restore的数据怎么取?

在View中,执行了onSaveInstanceState()后,View会将获取到的结果,保存在一个SparseArray中,这个SparseArray是从最根部的PhoneWindow中传递进来的,整个PhoneWindow中只有一份。

view中执行,container.put(mID, state);就会把自己要保存的数据放置到SparseArray中。

如果视图中存在id相同的View,那么后面保存的替换掉之前保存的。

在恢复数据时,也是从SparseArray中以当前View的Id为可以,获取保存的数据。获取到就是上一次保存时最后存储的数据。

Parcelable state = container.get(mID);  
if (state != null) {  // ……onRestoreInstanceState(state);// ……
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3163.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

只有IP没有域名怎么实现HTTPS访问

只有IP地址没有域名可以实现HTTPS访问?虽然通常情况下SSL证书是与域名关联并颁发的,但确实存在针对IP地址发放的SSL证书。这种类型的证书允许服务器通过HTTPS协议为其公网IP地址提供安全的Web服务。这意味着用户可以直接在浏览器中输入服务器的IP地址&am…

免翻!全球最大免费书库Zlibrary最新镜像,国内可直接访问,赶紧下书

刚刚,“知识大航海”群里,有位群友分享了一个Zlibrary镜像地址,感谢这位群友的热心分享,这个地址国内可以直接访问! 在“王不留”GZ号,写“zlib”四个字母,有Zlibrary镜像网址、官方网址&#x…

搜维尔科技:如何选择最佳的xsens动作捕捉设备

xsens介绍 如何选择最佳的xsens动作捕捉设备 选择最佳的 Xsens 动作捕捉设置并不总是像我们希望的那样简单。根据每个人的情况,会有不同的选择、要求和挑战。 这就是我们创建此博客的原因:帮助您做出最适合您的决定。 您已经决定继续使用 Xsens 了吗…

神经网络进阶

⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计3077字,阅读大概需要3分钟 🌈更多学习内容, 欢迎👏关注👀【文末】我的个人微信公众号&#xf…

19 使用MapReduce编程统计超市1月商品被购买的次数

首先将1月份的订单数据上传到HDFS上&#xff0c;订单数据格式 ID Goods两个数据字段构成 将订单数据保存在order.txt中&#xff0c;&#xff08;上传前记得启动集群&#xff09;。 打开Idea创建项目 修改pom.xml&#xff0c;添加依赖 <dependencies><dependency>…

微软发布Phi-3 Mini,性能媲美GPT-3.5、Llama-3,可在手机端运行

前言 微软发布了最新版的Phi系列小型语言模型(SLM) - Phi-3。这个系列包括3个不同参数规模的版本&#xff1a;Phi-3 Mini (38亿参数)、Phi-3 Small (70亿参数)和Phi-3 Medium (140亿参数)。 Phi系列模型是微软研究团队开发的小规模参数语言模型。从第一代Phi-1到第二代Phi-2&…

想把MP3音频转换成OGG格式需要什么工具?四种你不知道的音频转换工具在这里

​一&#xff0c;引言 随着数字音乐的发展&#xff0c;音频格式的种类也日益增多。MP3和OGG是其中两种常见的音频格式&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。有时&#xff0c;我们可能需要将MP3格式的音频转换为OGG格式&#xff0c;以满足特定的需求。本文…

JavaEE初阶——多线程(六)——线程池

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享多线程的第六篇文章,关于线程池 如果有不足的或者错误的请您指出! 目录 3.线程池3.1标准库的线程池3.2 标准库自己提供的几个工厂类3.3自己实现一个线程池完成大体框架接下来完…

LangChain的核心模块和实战

主要模型 LLM:对话模型, 输入和输出都是文本Chat Model: 输入输出都是数据结构 模型IO设计 Format: 将提示词模版格式化Predict: langchain就是通过predict的方式调用不同的模型, 两个模型的区别不大, Chat Model 是以LLM为基础的.Parese: langchain还可以对结果进行干预, 得…

解决Oracle锁表的方法

在实际工作中&#xff0c;并发量比较大的项目&#xff0c;经常会出现锁表的问题&#xff0c;下面我将复现这个问题&#xff0c;并给出解决方法。 一、问题复现 1、session1修改aabb表的B字段为迪迦奥特曼&#xff0c;但是不提交该事务。 2、session2也修改这行的这个字段。 发…

Prompt-to-Prompt Image Editing with Cross Attention Control

Prompt-to-Prompt Image Editing with Cross Attention Control TL; DR&#xff1a;prompt2prompt 提出通过替换 UNet 中的交叉注意力图&#xff0c;在图像编辑过程中根据新的 prompt 语义生图的同时&#xff0c;保持图像整体布局结构不变。从而实现了基于纯文本&#xff08;不…

终于有人把“Linux云计算路线”整理出来了,收藏起来,随时查看

一&#xff0c;计算机硬件 二&#xff0c;计算机网络 三&#xff0c;Linux系统管理 四&#xff0c;构建Linux服务系统&#xff0c;数据库&#xff0c;程序及Web服务 五&#xff0c;消息队列&#xff0c;web集群&#xff0c;系统及软件优化&#xff0c;智能化监控&#xff0c;海…

【大语言模型LLM】-基础语言模型和指令微调的语言模型

&#x1f525;博客主页&#xff1a;西瓜WiFi &#x1f3a5;系列专栏&#xff1a;《大语言模型》 很多非常有趣的模型&#xff0c;值得收藏&#xff0c;满足大家的收集癖&#xff01; 如果觉得有用&#xff0c;请三连&#x1f44d;⭐❤️&#xff0c;谢谢&#xff01; 长期不…

Qt Quick centerIn和fill 的用法

1&#xff09;Qt Quick centerIn和fill 的用法&#xff1a; import QtQuick 2.5 Rectangle { width:300; height:200; Rectangle { color: "blue"; anchors.fill: parent; border.width: 6; border.co…

qt QTreeWidget 学习

树形控件的节点可以有多层、多个子节点&#xff0c; 如果将子节点全部展开&#xff0c;那么每一行都是一个数据条目。QTreeWidgetItem 比较特殊&#xff0c;一个条目内部可以有多列数据信息&#xff0c;相当于表格控件一整行的表格单元集成为一个条目。 默认情况下&#xff0c;…

怎么保存微信视频号中的视频,赶紧看过来教你下载视频号里的视频!

视频内容已成为我们获取信息和娱乐的重要方式。微信视频号作为新兴的短视频平台&#xff0c;汇聚了丰富多样的创作&#xff0c;但有时我们希望将喜欢的视频保存到本地以便离线观看或分享给朋友。那么&#xff0c;视频号里的视频如何下载呢&#xff1f;别急&#xff0c;本文将详…

CCRC-DSO学员分享:数据安全官——导师与朋友的双重身份

我叫杜刚。在过去的几年里&#xff0c;我一直从事政企业务的工作&#xff0c;主要以网络安全业务为主导。尽管我已经有多年的政企与网络安全的工作经验&#xff0c;但我始终认为&#xff0c;不断学习和提升自己的专业能力是至关重要的。这就是我考取CCRC-DSO数据安全官证书的原…

11 - 在k8s官方文档上,经常搜索不到内容的问题

使用k8s官方文档时&#xff0c;会出现首页可以正常打开&#xff0c;但是输入搜索关键字之后&#xff0c;搜索不到内容的情况&#xff0c;如下图&#xff1a; 这是由于相关搜索组件被墙的原因&#xff0c;处理方法如下&#xff1a; 谷歌浏览器&#xff1a; 火狐浏览器&#x…

大模型实战—通义千问大模型微调

通义千问大模型微调 在之前的文章中&#xff0c;我分享了一些使用大语言模型开发应用的方法&#xff0c;也介绍了几个开源大语言模型的部署方式&#xff0c; 有同学给我留言说想知道怎么训练自己的大语言模型&#xff0c;让它更贴合自己的业务场景。完整的大语言模型训练成本…

springBoot集成seata实现分布式事务

背景 日常开发离不开分布式系统&#xff0c;自然避免不了分布式事务问题&#xff0c;Seata 是一款阿里开源的主流分布式事务解决方案&#xff0c;但实际工作引入seata感觉有点重&#xff0c;本人之前在商业银行做开发也很少团队使用。今天趁此机会做个demo&#xff0c;玩一玩了…