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.mfbz.cn/a/576094.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

就业班 第三阶段(负载均衡) 2401--4.18 day2 LVS-DR模式

3、LVS/DR 模式 实验说明: 1.网络使用NAT模式 2.DR模式要求Director DIP 和 所有RealServer RIP必须在同一个网段及广播域 3.所有节点网关均指定真实网关 主机名ip系统用途client172.16.147.1mac客户端lvs-server172.16.147.154centos7.5分发器real-server1172.16.…

SpringCloud简介

微服务架构理论 微服务架构概述 Spring Cloud简介Spring Cloud 技术栈SpringBoot和SpringCloud的关系SpringCloud和Dubbo区别对比相关文档 微服务架构概述 微服务是一种架构模式,将单一应用程序划分成一组小的服务,服务之间相互协调、相互配合&#xff0…

OSPF的LSA与特殊区域

Area区域概念 *一个区域维护一张LSDB,路由器详细的链路信息只在这个区域内传播 不是每一台路由器都需要了解所有外部目的地的详细信息 *OSPF网络的层次化设计 通过区域ID标识 骨干( Backbone )区域,必须是area 0(骨干区域…

milvus对象存储和消息中间件的工厂设计模式分析

milvus对象存储和消息中间件的工厂设计模式分析 需求 根据参数设置创建mq和storage mq有kafka,pulsar storage有local,minio,remote 配置文件 根据配置文件选择初始化mq和存储: mq:type: pulsarcommon:storageType: minio对于这种类型一个是mq,一个是存储&…

kubernetes部署控制器Deployment

一、概念 在学习rc和rs控制器资源时,这两个资源都是控制pod的副本数量的,但是,他们两个有个缺点,就是在部署新版本pod或者回滚代码的时候,需要先apply资源清单,然后再删除现有pod,通过资源控制&…

接口测试和Mock学习路线(上)

一、接口测试和Mock学习路线-第一阶段: 掌握接口测试的知识体系与学习路线掌握面试常见知识点之 HTTP 协议掌握常用接口测试工具 Postman掌握常用抓包工具 Charles 与 Fiddler结合知名产品实现 mock 测试与接口测试实战练习 1.接口协议: 需要先了解 O…

Vue3 + Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能(最新)

Vue3 Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能&#xff08;最新&#xff09; 1、效果展示2、实现代码2.1 GaoDeMap.vue2.2 SystemDialog.vue2.3 UnusedList.vue.vue 1、效果展示 2、实现代码 2.1 GaoDeMap.vue <template><div style…

【个人博客搭建】(11)swagger添加jwt信息

这个主要是为了方便使用swagger时&#xff0c;能更好的带入我们的token。 ps&#xff1a;如果使用其他第三方api工具&#xff08;apipost、postman等&#xff09;则不需要。 &#xff08;当然&#xff0c;不用不能没有&#xff0c;是吧&#xff09; 1、在AddSwaggerGen内添加…

文件权限管理

文件权限管理 1. 权限对象 权限对象含义u属主&#xff0c;所有者g属组o其他人 2. 权限类型 权限类型含义值r读权限4w写权限2x执行权限1 3. 修改文件属主及属组 命令:chown(change own)更改文件或目录属主与属组名 3.1 修改文件属主与属组 只修改属主&#xff1a;chown $…

【数据结构】链表的中间节点

给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 Definition for singly-linked list.struct ListNode {int val;struct ListNode *next;};typedef struct ListNode ListNode; struct ListNode…

美国服务器vs香港服务器,哪个网站部署打开更快一些?

网站打开速度受多种因素影响&#xff0c;包括服务器地理位置、网络质量、带宽等。用户距离服务器越近&#xff0c;访问速度越快。对于中国大陆用户而言&#xff0c;香港的服务器可能会提供更快的网站访问体验&#xff0c;因为香港距离大陆较近&#xff0c;且网络连接通常较好。…

python高阶函数:zip()

概述与基本用法 zip() 是 Python 内置函数之一&#xff0c;用于将多个可迭代对象打包成一个元组序列&#xff0c;然后返回一个迭代器。它可以接受任意数量的可迭代对象作为参数&#xff0c;并将它们的元素按顺序一一对应地打包成元组。 以下是 zip() 函数的基本用法&#xff…

2024年视频号小店来了,这次是不是新的电商风口?

大家好&#xff0c;我是电商糖果 2024年电商行业可以说大地震了&#xff0c;为什么这么说呢&#xff1f; 因为一个非常有实力的新平台出现了。 它就是微信视频号推出的视频号小店&#xff0c;也可以理解为腾讯旗下的电商平台。 视频号的出现是腾讯为了对标抖音&#xff0c;和…

使用LSTM网络实现文本情感分析

一、实验目的&#xff1a; 理解循环神经网络的基本概念和原理&#xff1b;了解循环神经网络处理文本数据的基本方法&#xff1b;掌握循环神经网络处理文本数据的实践方法&#xff0c;并实现文本情感分析任务。 实验要求&#xff1a; 使用Keras框架定义并训练循环神经网络模型…

链游:未来游戏发展的新风向

链游&#xff0c;即区块链游戏的一种&#xff0c;是一种将区块链技术与游戏玩法相结合的创新型游戏。它利用区块链技术的特性&#xff0c;如去中心化、可追溯性和安全性&#xff0c;为玩家提供了一种全新的游戏体验。链游通常采用智能合约来实现游戏的规则和交易系统&#xff0…

B站无限评论暴力截留协议及教程

B站无限评论暴力截留协议及教程 B站无限评论暴力截留协议及教程&#xff0c;需要抓CK &#xff0c;教程里面有讲如何抓取 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

森林消防隔膜泵的应用与前景——恒峰智慧科技

随着全球气候变暖&#xff0c;森林火灾频发&#xff0c;给生态环境和人类安全带来严重威胁。为有效应对这一挑战&#xff0c;森林消防领域不断引入新技术、新装备。其中&#xff0c;隔膜泵作为一种高效、可靠的消防设备&#xff0c;正逐渐受到广泛关注。本文将探讨森林消防隔膜…

c++在visual studio上的默认配置

右键 新建项 右键源文件 属性

5、Flink事件时间之Watermark详解

1&#xff09;生成 Watermark 1.Watermark 策略简介 为了使用事件时间语义&#xff0c;Flink 应用程序需要知道事件时间戳对应的字段&#xff0c;即数据流中的每个元素都需要拥有可分配的事件时间戳。 通过使用 TimestampAssigner API 从元素中的某个字段去访问/提取时间戳。…

Gitflow实操以及代码审查Pull Request操作

1.背景 之前一直有用过gitflow&#xff0c;但是一直没有归纳技术&#xff0c;另一方面也是每个团队用到的gitflow都不一致。而最近做项目要用gitflow&#xff0c;趁此机会分享一下gitflow的操作。 2.gitflow介绍 用git一直有一个问题&#xff0c;就是怎么保证代码稳定性&…
最新文章