返回

深入探讨 SavedInstanceState、Fragment.setRetainInstance 和 ViewModel 的异同

Android

如何保存数据以应对 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

常见问题解答

  1. 为什么 SavedInstanceState 只保存基本类型数据?
    SavedInstanceState 是一个 Bundle 对象,它只能存储基本类型数据。对于对象或自定义数据,开发者需要使用 ParcelableSerializable 接口来实现可序列化。

  2. 为什么 Fragment.setRetainInstance 会导致内存泄漏?
    Fragment.setRetainInstance(true) 会导致 Fragment 的实例在 Activity 被销毁后仍然保留。如果 Fragment 持有对 Activity 的引用,这可能会导致内存泄漏。

  3. ViewModel 如何管理数据生命周期?
    ViewModel 的数据生命周期与 Activity/Fragment 无关。它的数据会一直存在,直到 ViewModel 被销毁。

  4. 可以使用 SavedInstanceState 来保存对象吗?
    可以使用 SavedInstanceState 来保存可序列化的对象。开发者需要实现 ParcelableSerializable 接口,以便将对象写入和从 Bundle 中读取。

  5. 什么时候应该使用 ViewModel
    ViewModel 适用于需要在多个 Activity/Fragment 之间共享和管理数据的场景,或者需要持久化数据的场景。