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é.

  • ¿No puede haber una devolución dentro de un Runnable SAM en Kotlin?
  • Smart Cast no funciona como se esperaba
  • Kotlin, estructura del proyecto
  • ¿Conversión de Kotlin SAM con una interfaz Java interna privada?
  • ¿Por qué tengo que devolver Unit.INSTANCE al implementar en Java una function Kotlin que devuelve una Unidad?
  • Asignación no permitida en la expresión while?
  • ¿Cómo implementar esta interfaz Java en Kotlin?
  • Kotlin: atribuye visibilidad al object complementario
  • ¿Es posible acceder a las tipografías de Kotlin desde Java?
  • ¿Hay una sobrecarga para escribir una biblioteca en Kotlin para Android?
  • Kotlin utiliza la interfaz de callback de Java