onSaveInstanceState → SavedStateHandle
老写法(Java)
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("query", currentQuery);
outState.putInt("page", currentPage);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentQuery = savedInstanceState.getString("query");
currentPage = savedInstanceState.getInt("page");
}
}
问题在哪里
Activity 和 Fragment 要各自写保存/恢复逻辑。判断 savedInstanceState != null 然后是各种 get 方法的样板代码。如果用了 ViewModel,数据虽然在内存里不丢,但进程被杀死后还是没了。
新写法(ViewModel + SavedStateHandle)
class SearchViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
// 写法 1:直接读/写
var query: String
get() = savedStateHandle.get<String>("query") ?: ""
set(value) = savedStateHandle.set("query", value)
// 写法 2:用 StateFlow
private val _page = savedStateHandle.getStateFlow("page", 1)
val page: StateFlow<Int> = _page
fun nextPage() {
savedStateHandle.set("page", page.value + 1)
}
}
// Activity 里不再需要 onSaveInstanceState 和手动恢复
class SearchActivity : AppCompatActivity() {
private val viewModel: SearchViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewModel 里的数据通过 SavedStateHandle 自动恢复
}
}
一句话注意
SavedStateHandle 在进程被杀死后也能恢复数据——数据会被序列化保存到 onSaveInstanceState 的 Bundle 里,进程重建后自动恢复。但能保存的数据类型有限制:基本类型、String、Parcelable、Serializable 等。大对象或复杂引用不能用这个存。
ViewModel + SavedStateHandle 结合后,Activity/Fragment 的 onSaveInstanceState 基本可以从代码里删了——UI 相关的临时状态都交给 ViewModel 管理。
Java Android 老项目迁移系列,持续更新中。