状态恢复(State Restoration)是移动操作系统的一种机制,允许在应用重启或最小化后保存和恢复用户界面。系统将UI状态保存在内存或持久存储中,并在重新打开时恢复。根据Android Developers(2025)的数据,State Restoration对于追求高质量用户体验的应用是必需的。State Restoration对于防止应用意外关闭时的数据丢失至关重要。
要点
State Restoration(状态恢复)是一种系统机制,允许保存应用的当前用户界面状态,并在关闭或重启后恢复它。当用户最小化应用或系统为释放资源而关闭应用时,State Restoration会记录UI的关键参数并将其保存在加密存储中。
如果没有State Restoration,用户在应用间切换时会丢失所有未保存的数据。例如,已填写的联系表单、较长的搜索查询或部分浏览的新闻列表——所有这些在重启时都会消失。State Restoration通过在最小化时刻自动记录ViewController或Activity的状态来解决这个问题。
该机制在系统级别工作,并受到两个主要移动平台的支持。iOS通过NSUserActivity和UIStateRestoring协议提供State Restoration,而Android通过Jetpack架构组件中的SavedStateHandle和ViewModel提供。实现方式不同,但概念相同。
State Restoration过程分为两个阶段:保存(save)和恢复(restore)。在保存阶段,系统调用相应的生命周期方法,应用必须将当前UI状态序列化为紧凑表示。在恢复阶段,系统将保存的数据返回,应用将其反序列化以恢复UI。
保存由系统在应用进入后台模式或收到即将关闭的信号时启动。在iOS中,调用UIViewController中的encodeRestorableState方法,在Android中调用Activity中的onSaveInstanceState或通过SavedStateHandle保存。数据被序列化为支持原始类型的格式:字符串、数字、字节数组和Parcelable对象。
保存的数据量应尽可能小——系统对保存包的大小施加限制。在Android中,每个进程的限制约为50 KB。超出限制会导致TransactionTooLargeException异常。因此,架构师建议只保存标识符和键,而在恢复时从持久存储中加载完整数据。
恢复时,系统在启动时将保存的数据包传递给应用。在iOS中,调用decodeRestorableState方法,在Android中调用onRestoreInstanceState或从SavedStateHandle读取。应用从数据包中提取标识符和键,并恢复UI:滚动位置、选定元素、输入的数据。
重要的是要考虑恢复可能在新进程中发生。如果应用已从内存中完全卸载,进程会重新创建,内存中的所有对象都不存在。因此,状态必须是可序列化的,并且独立于先前会话的运行时上下文。这对于具有多个输入字段的大表单和长多页界面尤其关键。
class MainActivity : AppCompatActivity() {
private var searchQuery: String = ""
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("search_query", searchQuery)
}
override fun onRestoreInstanceState(savedState: Bundle) {
super.onRestoreInstanceState(savedState)
searchQuery = savedState.getString("search_query", "")!!
restoreSearchUI(searchQuery)
}
}
State Restoration的实现因平台而异。iOS通过storyboard和UIKit协议使用声明式方法,而Android通过Activity生命周期方法和Jetpack架构组件使用命令式方法。方法的选择取决于目标平台和应用架构。
在iOS中,State Restoration建立在三个组件之上:UIApplication管理整个过程,UIViewController实现UIStateRestoring协议,NSUserActivity存储用于恢复导航的数据。要启用,需要在UIViewController中设置restorationIdentifier并实现encodeRestorableState和decodeRestorableState。
iOS会自动保存导航控制器(UINavigationController)和所有嵌套的ViewController的状态,如果它们设置了restorationIdentifier。系统管理导航堆栈并将其恢复到原始状态。然而,控制器内部的数据(输入的文本、滚动位置)必须由开发人员显式保存。
在Android中,现代的State Restoration方法基于SavedStateHandle——一个来自AndroidX Lifecycle库的组件。SavedStateHandle在ViewModel内部可用,并在配置更改(屏幕旋转)和进程重启时自动保存和恢复数据。数据存储在Bundle中并自动序列化。
SavedStateHandle的行为类似于键值存储,支持LiveData。在配置更改时,数据会自动保存和恢复。为了支持进程重启,ViewModel必须通过SavedStateViewModelFactory创建——这允许ViewModel在应用完全关闭后继续存在。
class SearchViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
companion object {
private val KEY_QUERY = string("search_query")
}
fun getSearchQuery(): String? = savedStateHandle[KEY_QUERY]
fun saveSearchQuery(query: String) {
savedStateHandle[KEY_QUERY] = query
}
}
State Restoration的实际实现需要考虑几个方面:选择合适的存储、确定保存的数据量以及测试不同的关闭场景。让我们逐步看看如何使用state_restoration包为Flutter应用实现。
class RestorableSearchField extends RestorableProperty<String> {
String _value = '';
@override
String get value => _value;
@override
void set value(String newValue) {
if (_value != newValue) {
_value = newValue;
notifyListeners();
}
}
@override
String? toPrimitives() => _value;
@override
void fromPrimitives(String? data) {
_value = data ?? '';
}
}
在实现时,重要的是要记住保存的边界。并非每个UI字段都需要恢复。长列表中的滚动位置——是。动画的临时状态——否。开发人员应有意识地选择哪些数据对用户体验至关重要,哪些可以在不损失便利性的情况下安全重置。
测试State Restoration是一项独立的任务,需要模拟进程终止。在Android中,可以通过adb shell am kill命令完成,在iOS中则通过Xcode中的终止模拟完成。诸如Espresso和XCTest等UI测试框架提供了专门的方法来检查状态恢复。
第一条规则——保存标识符,而不是数据。与其保存具有数百个字段的完整对象,不如保存其唯一标识符,并在恢复时从数据库或API加载最新数据。这节省了Bundle中的空间,并保证了恢复时数据的时效性。
第二条规则——测试所有场景。检查屏幕旋转后的恢复、最小化一小时后返回后的恢复、以及系统因内存不足关闭应用后的恢复。每个场景可能因操作系统状态和可用资源的不同而表现不同。
第三条规则——使用系统机制,而不是自定义机制。iOS和Android提供了针对特定平台优化的内置State Restoration API。通过SharedPreferences或UserDefaults的自定义实现可能会导致同步问题和恢复时的意外行为。
第四条规则——处理状态缺失。在首次启动或清除数据后,状态可能不存在。UI应在初始状态下正常工作而不抛出异常。在使用前检查所有保存的数据是否为null,并提供默认值。
第五条规则——记录保存的键。当项目中有数十个屏幕且每个屏幕保存多个字段时,没有集中的键管理会导致混乱。在每个模块中为State Restoration创建一个包含键常量的统一类或文件。这简化了维护,并防止在重构时意外覆盖数据。
常见问题
State Restoration — 在应用重启或最小化后保存和恢复用户界面的机制,防止用户数据和工作上下文的丢失。
State Restoration保存UI的临时状态(滚动位置、表单中输入的数据),而数据库保存用户的永久数据。State Restoration使用具有容量限制的系统机制(Bundle、NSData)。
使用AndroidX Lifecycle中ViewModel中的SavedStateHandle。它在最小化时自动保存数据,并在返回时恢复。要支持完全重启,请使用SavedStateViewModelFactory。
在UIViewController中设置restorationIdentifier,并实现encodeRestorableState和decodeRestorableState方法。对于导航,使用NSUserActivity,并保存控制器堆栈中的路径。
保存标识符,而不是完整数据:选定元素的ID、搜索查询、滚动位置、开关状态。避免保存大对象和图像。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。