深入探讨 SavedInstanceState、Fragment.setRetainInstance 和 ViewModel 的异同
2023-09-16 19:29:05
如何保存数据以应对 Android 屏幕旋转
当涉及到 Android 屏幕旋转时,处理数据丢失是一个常见的痛点。屏幕旋转会导致 Activity 和 Fragment 被销毁和重建,从而导致数据丢失。为了解决这个问题,开发者可以利用各种技术来保存重要数据。
常见的保存数据技术
在 Android 中,有三种主要技术可以用于在屏幕旋转期间保存数据:
SavedInstanceState
Fragment.setRetainInstance
ViewModel
SavedInstanceState
SavedInstanceState
是一个 Bundle 对象,用于在 Activity 或 Fragment 被销毁之前保存其状态。在重建时,系统会自动将 SavedInstanceState
传递给 onCreate()
方法,开发者可以从中恢复保存的数据。
示例代码:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("myData", myData);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
myData = savedInstanceState.getString("myData");
}
}
Fragment.setRetainInstance
Fragment.setRetainInstance(true)
方法允许 Fragment 在其宿主 Activity 被销毁和重建后仍然保留。这意味着 Fragment 的实例不会被销毁,并且它保存的任何数据也不会丢失。
示例代码:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
ViewModel
ViewModel
是一个类,它独立于 Activity 和 Fragment 的生命周期,用于存储和管理数据。它通过双向数据绑定与 UI 交互,确保数据在 Activity/Fragment 旋转或销毁时保持同步。
示例代码:
public class MyViewModel extends ViewModel {
private MutableLiveData<String> myData = new MutableLiveData<>();
public void setData(String data) {
myData.setValue(data);
}
public LiveData<String> getData() {
return myData;
}
}
选择合适的方法
选择哪种技术取决于具体的使用场景:
- 如果需要保存基本类型数据,并且数据不需要在屏幕旋转后持久化, 可以使用
SavedInstanceState
。 - 如果需要保存对象或自定义数据,并且数据不需要在屏幕旋转后持久化, 可以使用
Fragment.setRetainInstance
。 - 如果需要持久化数据或在多个 Activity/Fragment 之间访问数据, 可以使用
ViewModel
。
常见问题解答
-
为什么
SavedInstanceState
只保存基本类型数据?
SavedInstanceState
是一个 Bundle 对象,它只能存储基本类型数据。对于对象或自定义数据,开发者需要使用Parcelable
或Serializable
接口来实现可序列化。 -
为什么
Fragment.setRetainInstance
会导致内存泄漏?
Fragment.setRetainInstance(true)
会导致 Fragment 的实例在 Activity 被销毁后仍然保留。如果 Fragment 持有对 Activity 的引用,这可能会导致内存泄漏。 -
ViewModel
如何管理数据生命周期?
ViewModel
的数据生命周期与 Activity/Fragment 无关。它的数据会一直存在,直到ViewModel
被销毁。 -
可以使用
SavedInstanceState
来保存对象吗?
可以使用SavedInstanceState
来保存可序列化的对象。开发者需要实现Parcelable
或Serializable
接口,以便将对象写入和从 Bundle 中读取。 -
什么时候应该使用
ViewModel
?
ViewModel
适用于需要在多个 Activity/Fragment 之间共享和管理数据的场景,或者需要持久化数据的场景。