Since I am not yet good in generics I would like to ask:
Question: why I cannot inform the function getResult that the return value from bundle.getParcelableCompat<T>(BUNDLE_KEY) would be type of T (which is any class inheriting by Parcelable)?
I get error:
Cannot use 'T' as reified type parameter. Use a class instead.
What am I mising? I though I passed all needed information what I am trying to achieve.
class MyClass<T : Parcelable>(
private val key: String,
private val clazz: Class<T>
) {
private inline fun <reified T : Parcelable> Bundle.getParcelableCompat(name: String): T? =
if (Build.VERSION.SDK_INT >= 33) {
this.getParcelable(name, T::class.java)
} else {
this.getParcelable(name)
}
fun getResult(fragment: Fragment, result: (T) -> Unit) = with(fragment) {
setFragmentResultListener(requestKey) { request, bundle ->
if (request == requestKey) {
val parcelableCompat: T? = bundle.getParcelableCompat<T>(BUNDLE_KEY)
parcelableCompat?.let(result)
}
}
}
}
As I said in this answer, reified type parameters in Kotlin are not magic. The compiler still needs a runtime-available type at the call site, so that it can inline your
getParcelableCompatmethod.To see how this does not work, just inline it yourself:
See how there is
T::class.java? You are trying to get the class of a non-reified type parameter, which is not allowed.In cases where you call
getParcelableCompatwith a non-type-parameter class, the inlining would come out fine. TheTinT::class.javawould be replaced with that class you used.Since the class type parameter
Tcannot be reified, there is really no point in makinggetParcelableCompathave a reified type parameter. It can accept aClass<T>instead:Alternatively, don't make
getParcelableCompatgeneric at all, since you can use the type parameterTfromMyClass