arkivanov / Essenty

The most essential libraries for Kotlin Multiplatform development
Apache License 2.0
495 stars 15 forks source link

Question: Is there a way to Parcelize generic type parameters in Sealed Classes? #90

Closed avidraghavMM closed 1 year ago

avidraghavMM commented 1 year ago

Hi, I have a generic parameter in a child class of a Sealed Class in Common Module. Generally if I had to parcelize this parameter in Android Module then I would have the @RawValue annotation coming from kotlinx.parcelize.RawValue . Is there any annotation provided by this library which can help me do the same?

My Sealed Class

import com.arkivanov.essenty.parcelable.Parcelable
import com.arkivanov.essenty.parcelable.Parcelize

/**
 * Generic class which can be used to describe the state of a screen
 */

@Parcelize
sealed class UIState<out T> : Parcelable {

    object Empty : UIState<Nothing>()

    object Loading : UIState<Nothing>()

    @Parcelize
    class Success<T>(val data: T) : UIState<T>()

    class Error(val exception: Exception) : UIState<Nothing>()
}

Getting this error for the data variable of Success class which is of type T:

Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'

arkivanov commented 1 year ago

Perhaps RawValue wouldn't help in all cases, because the data would be written with writeValue. It may crash at runtime if the actual type is not supported by writeValue.

You can try making T : Parcelable, if that's possible. However this may also not be working in some cases, e.g. when the actual class is in another ClassLoader.

A rule of thumb is to avoid generic types. You can make UIState not Parcelable, and parcelize it manually in every case where you otherwise specify the actual T. E.g. you can transform UIState<SomeClass> to a custom SavedUiStateWithSomeClass : Parcelable.

If you need this logic in the base code (where UIState is defined), then you can try supplying additional functions to save and restore UIState<T>. E.g. this could be:

Check out how it is done in Decompose.

avidraghavMM commented 1 year ago

Thanks for the quick reply I got it.