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

Ste*_*e M 11 android android-savedstate android-viewmodel

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

viewModel = ViewModelProvider(this, SavedStateViewModelFactory(requireActivity().application, savedStateRegistryOwner))
            .get(SelectedTracksViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚 SavedStateRegistryOwner。

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

Mir*_*iny 15

要为视图模型使用 Saved State 模块,您必须将androidx.lifecycle:lifecycle-viewmodel-savedstate依赖项添加到您的项目中。这个例子是基于 version 编写的1.0.0-rc03

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

视图模型实现:

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

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

    fun saveState() {
        state.set("liveData", liveDate.value)
    }
}
Run Code Online (Sandbox Code Playgroud)

活动实施:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果您已经通过“savedStateHandle.getLiveData”获取了 LiveData,则无需从“onSaveInstanceState”手动设置实时数据密钥。 (4认同)

Sup*_*try 6

我在这篇旧文章中添加了一个答案,以防有人发现它有用。

我设法做到了如下:

  • 将以下依赖项添加到“build.gradle(模块:app)”文件中
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Run Code Online (Sandbox Code Playgroud)
  • 将属性添加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
    }    
}
Run Code Online (Sandbox Code Playgroud)

最后在活动/片段中

    private val selectedTracksViewModel: SelectedTracksViewModel by lazy {
        ViewModelProvider(this).get(SelectedTracksViewModel::class.java)
    }
Run Code Online (Sandbox Code Playgroud)

就是这样。不需要SavedStateViewModelFactory,只需将savedState属性添加到ViewModel构造函数中并在跟踪属性更改时更新它即可。其他一切都像您没有使用一样工作,这种方式与活动/片段中的savedState: SavedStateHandle传统方式非常相似。onSaveInstanceState(Bundle)

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