Skip to content

Instantly share code, notes, and snippets.

@xxfast
Last active September 2, 2020 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xxfast/43f3193e06a9915969d0fc2a9ccecf2f to your computer and use it in GitHub Desktop.
Save xxfast/43f3193e06a9915969d0fc2a9ccecf2f to your computer and use it in GitHub Desktop.
A Polymorphic Parceler that enable to parcel any polymorphic type with @parcelize
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import kotlinx.android.parcel.Parceler
/**
* Enables any polymorphic type to be parcelled given they share an interface
*
* @sample
* ```kotlin
* sealed class Parent : Parcelable {
* @Parcelize
* class A : Parent {
* companion object : Parceler<A> by PolymorphicParceler.create()
* }
*
* @Parcelize
* class B : Parent {
* companion object : Parceler<B> by PolymorphicParceler.create()
* }
*
* companion object CREATOR : Creator<ResourceLogItem> by PolymorphicCreator.create(mapOf(
* A::class.java.name to A::class.java.classLoader,
* B::class.java.name to B::class.java.classLoader
* ))
* }
* ```
*/
class PolymorphicParceler<T : Parcelable>(private val classLoader: ClassLoader) : Parceler<T> {
override fun create(parcel: Parcel): T = requireNotNull(parcel.readParcelable(classLoader))
override fun T.write(parcel: Parcel, flags: Int) {
parcel.writeString(this::class.java.name)
this.writeToParcel(parcel, flags)
}
companion object {
inline fun <reified T : Parcelable> create(): PolymorphicParceler<T> =
PolymorphicParceler(requireNotNull(T::class.java.classLoader))
}
}
abstract class PolymorphicCreator<T : Parcelable>(
private val registry: Map<String, ClassLoader>) : Creator<T> {
override fun createFromParcel(parcel: Parcel): T {
val key: String = requireNotNull(parcel.readString()) { "type not using polymorphic parceler" }
val loader: ClassLoader = requireNotNull(registry[key]) { "$key no registered" }
val parcelable: T = requireNotNull(parcel.readParcelable(loader)) { "$key not parcelable" }
return parcelable
}
companion object {
inline fun <reified T : Parcelable> create(registry: Map<String, ClassLoader>) =
object : PolymorphicCreator<T>(registry) {
override fun newArray(size: Int): Array<T?> = arrayOfNulls(size)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment