简体   繁体   中英

Is there a way to use Kotlinx serialisation in an Android savedInstanceState Bundle?

It looks like the compiler doesn't want to use Kotlinx serialized classes in putSerializable and getSerializable . It says Type mismatch: inferred type is MyViewModel.SavedState but Serializable? was expected Type mismatch: inferred type is MyViewModel.SavedState but Serializable? was expected .

In my Activity:

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
}

In my 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?)

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 {
        ...
    }
}

I'm pretty sure Kotlinx.Serialization is not OOB compatible with Bundle's putSerializable. However, you could just stringify your SavedState , send it via putString and on the receiving end deserialize string back to your class.

You could use the kotlin-parcelize plugin ( https://developer.android.com/kotlin/parcelize )

First add the plugin to your app/build.gradle:

plugins {
    ..
    id 'kotlin-parcelize'
}

Then add the @Parcelize annotation and the Parcelable interface to a class:

import kotlinx.parcelize.Parcelize

@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable

And then you can add an instance to a bundle:

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

However, the kotlin-parcelize plugin does not seem to work with sealed classes, so it may not be the right solution for your usecase.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM