如何使用 ViewModel 的新保存状态模块

How do I use the new Saved State Module of ViewModel

我使用的是生命周期版本 2.2.0-rc03 和 official docs,发现的文章甚至没有列出正确的 class 名称或构造函数参数。我想我必须通过这样的方式获取 ViewModel 实例

viewModel = ViewModelProvider(this, SavedStateViewModelFactory(requireActivity().application, savedStateRegistryOwner))
            .get(SelectedTracksViewModel::class.java)

但我不知道 SavedStateRegistryOwner。

有人可以举一个简单的例子来说明如何创建保存状态的 ViewModel 实例以及在 ViewModel 中保存和恢复值的正确方法吗?

据我了解,您想使用规范构造函数创建视图模型。 您可以使用 ViewModelProvider.Factory.

viewModel = ViewModelProvider(this, SavedStateViewModelFactory.create(state)
            .get(SelectedTracksViewModel::class.java)

ViewModelFactory 示例

public class SavedStateViewModelFactory {

    public static <E> ViewModelProvider.Factory create(State state){

        return new ViewModelProvider.Factory() {
            @NonNull
            @Override
            @SuppressWarnings("unchecked")
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                if (modelClass.isAssignableFrom(SelectedTracksViewModel.class)) {
                    return (T) new SelectedTracksViewModel<>(state);
                } else {
                    throw new IllegalArgumentException("Unknown ViewModel class");
                }
            }
        };
    }

}

要为视图模型使用保存状态模块,您必须将 androidx.lifecycle:lifecycle-viewmodel-savedstate 依赖项添加到项目中。本例基于1.0.0-rc03.

版本编写

请将以下行添加到您的项目 Gradle 文件中:
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-rc03'

视图模型实现:

class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() {

    val liveData = state.getLiveData("liveData", Random.nextInt().toString())

    fun saveState() {
        state.set("liveData", liveData.value)
    }
}

Activity 实施:

class SavedStateActivity : AppCompatActivity() {

    lateinit var viewModel: SavedStateViewModel;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityStateBinding = DataBindingUtil.setContentView(this, R.layout.activity_state)

        viewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(SavedStateViewModel::class.java)

        binding.viewModel = viewModel
        binding.lifecycleOwner = this
    }

    override fun onSaveInstanceState(outState: Bundle) {
        if(::viewModel.isInitialized)
            viewModel.saveState()

        super.onSaveInstanceState(outState)
    }
}

我已经测试了这段代码,它工作正常。

我正在为这个旧 post 添加一个答案,以防万一有人觉得它有用。

我设法做到了,如下所示:

  • 将以下依赖项添加到您的“build.gradle(模块:app)”文件
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  • savedState: SavedStateHandle属性添加到ViewModel
  • 的构造函数中
class SelectedTracksViewModel(private val savedState: SavedStateHandle) : ViewModel() {

    companion object {
        private const val SAVED_TRACK_INDEX = "savedTrackIndex"
    }

    private var trackIndex: Int
      set(value) {
        field = value
        // Simply update the savedState every time your saved property changes
        savedState.set(SAVED_TRACK_INDEX, value)
      }

    init {
        trackIndex = savedState.get<Int>(SAVED_TRACK_INDEX) ?: 0
    }

    fun moveToNextTrack() {
        trackIndex++ 
        // Initially I was updating savedState here - now moved to setter
        
        // Some more code here
    }    
}

终于在activity/fragment

    private val selectedTracksViewModel: SelectedTracksViewModel by lazy {
        ViewModelProvider(this).get(SelectedTracksViewModel::class.java)
    }

就是这样。不需要 SavedStateViewModelFactory,只需将 savedState 属性 添加到您的 ViewModel 构造函数并在跟踪属性更改时更新它。其他一切都像你没有使用 savedState: SavedStateHandle 一样工作,这种方式与 activities/fragments.

中的传统 onSaveInstanceState(Bundle) 非常相似

更新: 最初我是在更改 trackIndex 后更新 savedState。这意味着每次 保存的属性更改时都必须更新 savedState 。如果忘记添加该行,这将是一个巨大的潜在未来错误。一个更好更健壮的模式是更新 属性.

的 setter 中的 savedState