有没有一种优雅的方式来保存和恢复 Kotlin 中的视图状态?

And*_*Res 14 android parcelable kotlin

编写在 Android 中跨配置更改保持状态的自定义视图是冗长的,看看用于保存一个字段状态的样板代码的数量:

private class SavedState : BaseSavedState {
        var amount: Int = 0

        constructor(parcel: Parcel) : super(parcel) {
            amount = parcel.readInt()
        }

        constructor (parcelable: Parcelable?) : super(parcelable)

        override fun writeToParcel(parcel: Parcel, flags: Int) {
            super.writeToParcel(parcel, flags)
            parcel.writeInt(amount)
        }

        companion object CREATOR : Parcelable.Creator<SavedState> {
            override fun createFromParcel(parcel: Parcel): SavedState {
                return SavedState(parcel)
            }

            override fun newArray(size: Int): Array<SavedState?> {
                return arrayOfNulls(size)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Android Extensions 插件提供了@Parcelize可以用来自动生成 的实现的注释Parcelable,但是在自定义视图的情况下,我们必须BaseSavedStateParcelable.

所以,有这样的东西不会编译:

@Parcelize
data class SavedState(val isLoading: Boolean = false): BaseSavedState()
Run Code Online (Sandbox Code Playgroud)

我想知道在自定义视图中是否有一种不太冗长的处理状态恢复的方法。将不胜感激任何想法或建议。

moh*_*sen 9

编写一个SaveState类是一种将需要保存的所有数据打包到一个类中的方法。另一种方法是覆盖onSaveInstanceStateonRestoreInstanceState把你的参数放在一个包中。这避免了你提到的样板。如果您有多个参数,只需使用带@Parcelize注释的数据类并使用bundle.putParcelable.(而不是本例中的数量)保存该类。也不要忘记设置isSaveEnabled为true。

init { isSaveEnabled = true }

...

override fun onSaveInstanceState(): Parcelable {
   val bundle = Bundle()
   bundle.putInt("amount", amount)
   bundle.putParcelable("superState", super.onSaveInstanceState())
   return bundle
}
Run Code Online (Sandbox Code Playgroud)
override fun onRestoreInstanceState(state: Parcelable) {
 var viewState = state
 if (viewState is Bundle) {
   amount = viewState.getInt("amount", 0)
   viewState = viewState.getParcelable("superState")
 }
 super.onRestoreInstanceState(viewState)
}
Run Code Online (Sandbox Code Playgroud)


Iul*_*scu 8

@Parcelize注释仍然可以使用,因为我们必须扩展的基类BaseSavedState实现了Parcelable。这是一个示例,我需要在我定义的自定义视图中保存一些持续时间。

@Parcelize
internal class SavedState(state: Parcelable?, val duration: Long) : BaseSavedState(state)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我们可以使用注释来仅定义我们想要保存的状态和字段。一旦我们准备好状态,我们就可以像这样保存/恢复它:

override fun onSaveInstanceState(): Parcelable {
    val parcel = super.onSaveInstanceState()
    return SavedState(parcel, currentDuration.timeInMillis)
}

override fun onRestoreInstanceState(state: Parcelable?) {
    if (state !is SavedState) {
        super.onRestoreInstanceState(state)
        return
    }

    super.onRestoreInstanceState(state.superState)
    setDurationInMillis(state.duration)
}
Run Code Online (Sandbox Code Playgroud)

从这个实现开始,您可以添加Parcelable状态类的参数并将其传递给基类。这样,一切都应该正常进行。