Closed Deaths-Door closed 1 year ago
This is an Android limitation. You can only save/restore primitives and Parcelables
(and there's also an 50K size limit)
However, if you wish to parcel an external type - say UUID - you must write a custom parceler for this. Instructions for that is documented here, but the gist is
// commonMain
expect object UuidParceler : Parceler<UUID>
// androidMain
actual object UuidParceler : Parceler<UUID> {
// I'm not sure what the exact API to create a uuid from string, but hoping something like this
override fun create(parcel: Parcel): UUID = UUID(parcel.readString())
override fun UUID.write(parcel: Parcel, flags: Int) {
parcel.writeString(this.toString())
}
}
Then on state declaration
@Parcelize
@TypeParceler<UUID, UuidParceler>()
data class Album(
val id : UUID = UUID.random(),
val name : String,
val image : String? = null,
val songs : MutableList<MediaItem> = mutableListOf(),
val isPinned : Boolean = false
): Parcelable
Also, due to the Android bundle size limitation (of 50K) - I strongly advise limiting the amount of data that goes into the state. Especially with a MutableList<MediaItem>
, parceling a Album
can easily blow up more than 50k
Yes, you're right. While it's true that Android imposes a limitation where you can only save and restore primitives and Parcelables. Serializing complex objects into a string representation allows for easier usage and handling of those objects. It provides a more flexible approach, enabling the storage and retrieval of complex data structures.. A potential solution is to serialize the object into a string representation and then deserialize it back into an object. By utilizing KClazz and handling the serialization process, this approach can be more effective and efficient. Maybe something like this ..
data class Other(
val id : UUID = UUID.random()
) : Parcelable // extending parcelable as router accepts this type .
Then I'm not sure how it handles the checking internally so maybe just add a check
inline fun <refied T>checkOrThrowError(clazz : KClazz<T>) {
if(clazz has serializer) //add flag to serialize and deserialize it instead
else // default checking
}
It opens up possibilities for easily integrating object serialization and deserialization into their codebase, without having to manually handle the conversion of complex objects + external classes.
This goes a little over the scope of this library but generally, Decompose-Router will always delegate state management to the underlying platform.
There are also other considerations, like
While I agree, it is cumbersome to make states extend existing parcelisation implementations - on Android, this is the only native way to achieve state restoration unfortunately.
Just wanted to say that the bundle limit is ~500k (not 50k) on Android, shared across the whole app's process.
Issue Description
I encountered an issue while using the Decompose-Router library where passing arguments using the
@Parcelize
annotation is not supported for complex objects with external classes that don't extend Parcelize.Where Album is a complex object containing external classes that don't extend Parcelize.
I've considered using the @RawValue annotation, but that is specific to Android and not suitable for this scenario. Additionally, using expect/actual declarations would defeat the purpose of using the Decompose-Router library.
I suggest two potential solutions:
@Serialization
annotation.