Kotlin: No se puede usar GenericTypeIndicator para llamar al getValue de Firebase Database

Al usar Kotlin para trabajar con la database de Firebase, parece que no puedo recuperar un valor de tipo List<String> si uso un GenericTypeIndicator siguiente manera:

 snap.getValue(object : GenericTypeIndicator<List<String>>() {}) 

Produce una exception del SDK de Firebase de la siguiente manera:

 com.google.firebase.database.DatabaseException: Generic wildcard types are not supported at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.firebase.database.DataSnapshot.getValue(Unknown Source) 

Sin embargo, si lo llamo desde Java, de la siguiente manera, funciona:

 snap.getValue(new GenericTypeIndicator<List<String>>() {}) 

Estaba adivinando que tiene que ver con el tipo de reificación, así que hice esto:

 inline fun <reified T> genericType() = object: GenericTypeIndicator<T>() {} val stringListIndicator = genericType<List<String>>() snap.getValue(stringListIndicator) 

pero la misma exception sucedió.

¿Por que es esto entonces?


Editar: Intenté descomstackr las versiones de Java y Kotlin usando jadx-0.6.1.

Fuente de Java:

 public class Randommmm { private static final GenericTypeIndicator<List<String>> ti = new GenericTypeIndicator<List<String>>() { }; public static List<String> x(DataSnapshot snap) { return snap.getValue(ti); } } 

Descomstackdo:

 public class Randommmm { private static final GenericTypeIndicator<List<String>> ti = new C12761(); static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } public static List<String> m48x(DataSnapshot snap) { return (List) snap.getValue(ti); } } 

Fuente de Kotlin (1):

 object Randommmm { private val ti = object : GenericTypeIndicator<List<String>>() { } fun x(snap: DataSnapshot): List<String> { return snap.getValue(ti) } } 

Descomstackdo:

 public final class Randommmm { public static final Randommmm INSTANCE = null; private static final Randommmm$ti$1 ti = null; static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } static { Randommmm randommmm = new Randommmm(); } private Randommmm() { INSTANCE = this; ti = new Randommmm$ti$1(); } @NotNull public final List<String> m48x(@NotNull DataSnapshot snap) { Intrinsics.checkParameterIsNotNull(snap, "snap"); Object value = snap.getValue(ti); Intrinsics.checkExpressionValueIsNotNull(value, "snap.getValue(ti)"); return (List) value; } } public final class Randommmm$ti$1 extends GenericTypeIndicator<List<? extends String>> { Randommmm$ti$1() { } } 

Fuente de Kotlin (2) usando ArrayList como lo sugirió Doug:

 object Randommmm { private val ti = object : GenericTypeIndicator<ArrayList<String>>() { } fun x(snap: DataSnapshot): List<String> { return snap.getValue(ti) } } 

Descomstackdo:

 public final class Randommmm { public static final Randommmm INSTANCE = null; private static final Randommmm$ti$1 ti = null; static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } static { Randommmm randommmm = new Randommmm(); } private Randommmm() { INSTANCE = this; ti = new Randommmm$ti$1(); } @NotNull public final List<String> m48x(@NotNull DataSnapshot snap) { Intrinsics.checkParameterIsNotNull(snap, "snap"); Object value = snap.getValue(ti); Intrinsics.checkExpressionValueIsNotNull(value, "snap.getValue(ti)"); return (List) value; } } public final class Randommmm$ti$1 extends GenericTypeIndicator<ArrayList<String>> { Randommmm$ti$1() { } } 

En Kotlin,

 val ti = object : GenericTypeIndicator<List<String>>() {} 

se genera como (en Java):

 SyntethicClass ti = new SyntethicClass(); public final class SyntethicClass extends GenericTypeIndicator<List<? extends String>> {} 

Observe el comodín ? extends String ? extends String lugar de simplemente String .

Consulte https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#variant-generics para get una explicación.

Para evitar eso, anote el parámetro de tipo con @JvmSuppressWildcards :

 val ti = object : GenericTypeIndicator<List<@JvmSuppressWildcards String>>() {} 

Esto se vuelve súper feo, pero funciona. Alternativamente, use ArrayList según la respuesta de Doug .

Intenta cambiar esta línea:

 snap.getValue(object : GenericTypeIndicator<List<String>>() {}) 

A esto:

 snap.getValue(object : GenericTypeIndicator<ArrayList<String>>() {}) 

Funciona para mí, pero no sé por qué.

  • Sintaxis de Kotlin para inferir supertipo genérico de subtipo
  • Buscador privado y establecedor público para una propiedad de Kotlin
  • ¿Cómo se usa Flowable.generate de Kotlin?
  • Anular setter para la variable definida en el constructor pnetworkingeterminado
  • String :: toByteArray () no se comstack en Kotlin
  • Pasar un object detector como un parámetro de function en kotlin
  • Conversión de la implementación Thread / Runnable de Java a Kotlin
  • ¿Cómo implementar esta interfaz Java en Kotlin?