Android Saving Activity State使用说明和注意事项

2024-05-14 10:44

本文主要是介绍Android Saving Activity State使用说明和注意事项,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、说明

在管理activity生命周期的简单介绍中提到当一个activity被暂停或停止时,该activity的状态被保留。因为当activity对象被暂停或停止时仍然保留在内存中,所有有关成员的信息和当前的状态仍然可用。这样,用户对该activity所做的任何更改都会保留并当恢复时这些变化仍然存在。

然而,当系统为了恢复内存而销毁activity对象时,该activity对象就被销毁了,因此系统不能简单的通过状态恢复它。相反,当用户从新回到该界面时系统必须重新创建activity对象。然而,用户并不知道系统销毁了该activity对象并重新创建了它,这样,很可能期望这个界面就是之前的那个。在这种情况下,必须保证有关activity状态的重要信息通过实现额外的回调函数来保存有关activity状态的信息:onSaveInstanceState()。

在该activity受到破坏之前调用onSaveInstanceState()方法。系统传递一个Bundle对象到该方法,一个Bundle利用putString()和putInt()方法以键值对的形式保存activity的状态信息。这时,当系统杀掉应用程序进程,用户又回到之前的界面,系统重新创建一个activity并传递Bundle到onCreate()和onRestoreInstanceState()方法。利用任一个方法,可以从Bundle中提取保存的状态信息并恢复该Activity的状态。如果没有状态信息需要恢复,这时传递的Bundle是null(当第一次创建activity时)。

在这里插入图片描述
然而,即便你没做任何事情并且也没有实现onSaveInstanceState(),一些activity状态也会通过activity类默认的onSaveInstanceState()实现来存储。具体来说,默认的实现为布局中的每个View调用相应的onSaveInstanceState()方法,在该方法里每个view提供需要保存的自身的信息。几乎Android框架中的每个组件都适当的实现了该方法,例如,UI上的任何可视的变化都能自动的保存并在该Activity重新创建时恢复。例如,EditText部件保存用户输入的任何文本,CheckBox保存是否被选中。你需要做的唯一工作是为每个需要保存状态的组件提供一个唯一的ID(利用android:id属性),如果一个组件没有ID,系统不能保存它的状态(一般情况是xml上提供一个ID,如果是代码上布局的组件,就用setId(int id)提供一个ID)。

虽然onSaveInstanceState()默认实现能够保存Activity的一些有用信息,但还是需要覆盖它保存一些额外的信息。例如,需要在activity生命周期中保存更改的成员值(这需要在UI中恢复这些值相关,但是持有这些值的成员不会被恢复)。

如果重新了onSaveInstanceState()方法,在实现中应该调用父类的方法,以存储默认的信息。同时在onRestoreInstanceState()中也调用父类的方法以恢复默认的信息。

注意:由于onSaveInstanceState()方法不保证一定会被调用,你应该用它只记录activity的临时状态而不是持久数据。相反,在onPause()里来存储持久数据。

测试应用程序恢复状态能力的好方法是简单的旋转设备以使屏幕方向改变。当方向改变时,系统销毁并重新创建这个Activity以应用可选的资源,这些资源在新屏幕配置中使用。出于这个原因,当activity重新创建时完全恢复其状态是很重要的,应用用户在使用应用时经常旋转屏幕。

Handling configuration changes

有些设备配置在运行时会改变(例如,屏幕方向,键盘可用性,和语言)。当这些变化发生时,Android重新创建这个运行着的Activity(系统调用onDestroy(),然后立即调用onCreate()),这种行为可以帮助应用程序采用新的配置,通过自动加载应用程序利用你提供的可选资源(不同的屏幕和大小采用不同的布局)。

如果你能正确的设计activity来处理由于屏幕方向变化和恢复activity状态导致的重启,你的应用程序会对activity生命周期中的突发事件更有弹性。

处理这种重启事件最好的方法就是存储和恢复你的activity的状态,通过调用onSaveInstanceState()和onRestoreInstanceState()(或onCreate())。

当一个activity启动另一个,他们都需要进行生命周期转换。第一个activity暂停和停止。而另一个activity被创建。这种情况下这些activities共享保存到光盘或其他地方的数据,重要的是理解在第二个activity被创建之前第一个activity是没有完全停止的。相反,启动第二个的过程和停止第一个的过程是重叠的。

生命周期中回调的顺序需要友好定义,特别是当两个activities在同一个进程里,一个启动另一个。下面是当A启动B时的顺序:
1, A的onPause()方法执行
2, B的onCreate(),onStart()和onResume()方法执行
3, 这时,如果A在屏幕上已不可见,onStop()方法执行。

2、实操

2.1、使用 onSaveInstanceState() 保存简单轻量的界面状态

当您的 Activity 开始停止时,系统会调用 onSaveInstanceState() 方法,以便您的 Activity 可以将状态信息保存到实例状态 Bundle 中。此方法的默认实现保存有关 Activity 视图层次结构状态的瞬时信息,例如 EditText 微件中的文本或 ListView 微件的滚动位置。

如需保存 activity 的其他实例状态信息,请替换 onSaveInstanceState(),并将键值对添加到在 activity 意外销毁时保存的 Bundle 对象。替换 onSaveInstanceState() 时,如果您希望默认实现保存视图层次结构的状态,则需要调用父类实现。具体可见以下示例:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...@Override
public void onSaveInstanceState(Bundle savedInstanceState) {// Save the user's current game state.savedInstanceState.putInt(STATE_SCORE, currentScore);savedInstanceState.putInt(STATE_LEVEL, currentLevel);// Always call the superclass so it can save the view hierarchy state.super.onSaveInstanceState(savedInstanceState);
}

注意 :当用户显式关闭 activity 或其他情况下,当调用 finish() 时,系统不会调用 onSaveInstanceState()。

如需保存持久性数据(例如用户偏好设置或数据库的数据),请在 activity 位于前台时抓住适当的机会。如果没有这样的时机,请在使用 onStop() 方法期间保存持久性数据。

2.2、使用保存的实例状态恢复 Activity 界面状态

重建先前被销毁的 Activity 后,您可以从系统传递给 Activity 的 Bundle 中恢复保存的实例状态。onCreate() 和 onRestoreInstanceState() 回调方法都会接收包含实例状态信息的同一 Bundle。

由于无论系统是创建新的 activity 实例还是重新创建之前的实例,都会调用 onCreate() 方法,因此您需要先检查状态 Bundle 是否为 null,然后再尝试读取它。如果为 null,系统将新建 Activity 实例,而不会恢复之前销毁的实例。

以下代码段展示了如何在 onCreate() 中恢复某些状态数据:

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); // Always call the superclass first// Check whether we're recreating a previously destroyed instance.if (savedInstanceState != null) {// Restore value of members from saved state.currentScore = savedInstanceState.getInt(STATE_SCORE);currentLevel = savedInstanceState.getInt(STATE_LEVEL);} else {// Probably initialize members with default values for a new instance.}// ...
}

您可以选择实现系统在 onStart() 方法之后调用的 onRestoreInstanceState(),而不是在 onCreate() 期间恢复状态。仅当存在要恢复的已保存状态时,系统才会调用 onRestoreInstanceState(),因此您无需检查 Bundle 是否为 null。

public void onRestoreInstanceState(Bundle savedInstanceState) {// Always call the superclass so it can restore the view hierarchy.super.onRestoreInstanceState(savedInstanceState);// Restore state members from saved instance.currentScore = savedInstanceState.getInt(STATE_SCORE);currentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

注意:请始终调用 onRestoreInstanceState() 的父类实现,以便默认实现可以恢复视图层次结构的状态。

觉得本文对您有用,麻烦点赞、关注、收藏,您的肯定是我创作的无限动力,谢谢!!!

这篇关于Android Saving Activity State使用说明和注意事项的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/988528

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud