Last active
September 2, 2020 12:57
-
-
Save xxfast/43f3193e06a9915969d0fc2a9ccecf2f to your computer and use it in GitHub Desktop.
A Polymorphic Parceler that enable to parcel any polymorphic type with @parcelize
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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