Check reified class is Parcelable or Serializable

397 views Asked by At

I have defined an inline method that provides a way to deserialize fragments argument.

And I need to check requested Arg type to choose deserialization method.

inline fun <reified Arg : Any?> Fragment.navArgParser(
    crossinline parcelCreatorProducer: () -> Parcelable.Creator<Arg>
) = NavArgsLazy<Arg?>({
    arguments ?: throw IllegalStateException("Fragment $this has null arguments")
}) {
    when {
        Arg is Parcelable ->   // ISSUE
            NavArgParser.deserializeData<Arg>(it, parcelCreatorProducer.invoke())
        Arg is Serializable ->  // ISSUE
            NavArgParser.deserializeData<Serializable>(it) as Arg
        else ->
            throw IllegalStateException("${Arg::class.java.simpleName} must implement Parcelable or Serializable")
    }
}

How can I check Arg is Parcelable or Serializable?

2

There are 2 answers

2
Amin On BEST ANSWER

Arg is not an object so you cannot use is. You should use isAssignableFrom which accepts a class object

when {
    Parcelable::class.java.isAssignableFrom(Arg::class.java) -> //
    ...
}

You can also write some extension like:

inline fun <reified L : Any, reified R : Any> isSubClassOf() = R::class.java.isAssignableFrom(L::class.java)

inline fun <reified L : Any, reified R : Any> isSuperClassOf() = L::class.java.isAssignableFrom(R::class.java)

And use it like

when{
    isSuperClassOf<Parcelable, Arg> -> //
1
seyed Jafari On

There are two ways to check type equality purely in Kotlin (no java translation):

  1. checking if a class is a subClass of a parent class:

inline fun <reified A> checkSubclasses(){
    if(A::class.isSubclassOf(Serializable::class)){
        println("it's a serializable")
    }
    if(A::class.isSubclassOf(Parcelable::class)){
        println("it's a parcelable")
    }
}

  1. finding a class type and then checking if type A is a subType of B:
@ExperimentalStdlibApi
inline fun <reified A> checkType() {
    val argType = typeOf<A>()

    if(argType.isSubtypeOf(typeOf<Serializable>())){
        println("it's a serializable")
    } else if (argType.isSubtypeOf(typeOf<Parcelable>())){
        println("it's a parcelable")
    }
}

typeOf can be used in more cases yet please note the typeOf function is still experimental.