【问题标题】:Is there a way to use Kotlinx serialisation in an Android savedInstanceState Bundle?有没有办法在 Android savedInstanceState Bundle 中使用 Kotlinx 序列化?
【发布时间】:2020-06-19 07:19:54
【问题描述】:

看起来编译器不想在 putSerializablegetSerializable 中使用 Kotlinx 序列化类。 上面写着Type mismatch: inferred type is MyViewModel.SavedState but Serializable? was expected

在我的活动中:

override fun onCreate(savedInstanceState: Bundle?) {
    AndroidInjection.inject(this)
    super.onCreate(savedInstanceState)

    setContentView(R.layout.my_activity_layout)

    viewModel.init(savedInstanceState?.getSerializable(SAVE_STATE) as? SavedState) // compiler complains here
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putSerializable(SAVE_STATE, viewModel.buildSaveState()) // and here
}

在我的 ViewModel 中:

fun buildSaveState(): SavedState =
        SavedState(value1, value2, value3, value4)

@Serializable
data class SavedState(val foo: Boolean?,
                      val foo1: Enum1?,
                      val foo2: Enum2?,
                      val foo3: MyType?)

我的类型:

@Serializable
sealed class MyType {
    data class MyType1(val foo4: Enum3) : MyType()
    data class MyType2(val foo5: Enum4) : MyType()

    enum class Enum3 {
        ...
    }

    enum class Enum4 {
        ...
    }
}

【问题讨论】:

    标签: android kotlin serialization bundle kotlinx


    【解决方案1】:

    我很确定 Kotlinx.Serialization 与 Bundle 的 putSerializable 不兼容 OOB。但是,您可以只 stringify 您的 SavedState,通过 putString 发送它,然后在接收端将字符串反序列化回您的班级。

    【讨论】:

    • 感谢这项工作,我通过传入从SavedState.serializer() 获得的序列化程序类(类型KSerializer<T>)使用了Json.stringify(serializer, value)Json.parse(serializer, value)。我还必须将@Serializable 添加到密封类的每个子类中。
    • stringify 函数从何而来?我无法在来自 kotlinx.serialization.json 的 Json 对象上找到它。是否已重命名为 encodeToString?
    • 是的,Kotlinx.serialization 使用 encodeToString 和 decodeFromString 进行序列化/反序列化。
    【解决方案2】:

    您可以使用 kotlin-parcelize 插件 (https://developer.android.com/kotlin/parcelize)

    首先将插件添加到你的 app/build.gradle:

    plugins {
        ..
        id 'kotlin-parcelize'
    }
    

    然后将@Parcelize注解和Parcelable接口添加到一个类中:

    import kotlinx.parcelize.Parcelize
    
    @Parcelize
    class User(val firstName: String, val lastName: String, val age: Int): Parcelable
    

    然后您可以将实例添加到捆绑包中:

    val user = User("John", "Doe", 33)
    bundle.putParcelable("mykey", user)
    

    但是,kotlin-parcelize 插件似乎不适用于密封类,因此它可能不是您用例的正确解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-30
      • 1970-01-01
      相关资源
      最近更新 更多