¿Es posible distribuir una clase genérica?
Estoy intentando crear public class MyClass<T extends Parcelable> implements Parcelable
. Tengo problemas para implementar Parcelable
. ¿Es posible crear una clase genérica que implemente Parcelable
? (Tenga en cuenta que T
está limitado de modo que también debe implementar Parcelable
).
Estoy teniendo problemas con el hecho de que la interfaz Parcelable requiere una variable estática : public static final Parcelable.Creator<MyParcelable> CREATOR
. Por lo tanto, no puedo hacer public static final Parcelable.Creator<MyClass<T>> CREATOR
MyParcelable<T>
porque MyParcelable<T>
no es estadístico.
- Objetivo y Parcelable objeto Android
- ClassNotFoundException cuando unmarshalling y realmente no sé por qué
- Clase no encontrada cuando Unmarshalling Android Intent Parcelable
- Android | Unmarshalling Tipo desconocido al utilizar datos parcelables en paquetes
- Problema de desacoplamiento de parcelables
André
- Anidado Parcelling: RuntimeException - Unmarshalling tipo desconocido código 3211319 en el desplazamiento 440
- Cómo obtener ClassLoader de variable de tipo (para parcelar una clase usando genéricos)
- Escritura de arreglos de Parcelables a un paquete en Android
- Escribir enum con String a paquete
- Cómo guardar ArrayList personalizado en la rotación de la pantalla de Android?
- Cómo en Android pasar un objeto a un nuevo propósito
- Casting objetos a subclases de una superclase Parcelable?
- Android Class Parcelable con ArrayList
Tuve problemas similares con la implementación de Parcelable en una clase con un genérico, el primer problema era el mismo que lo que estaba experimentando:
Por lo tanto, no puedo hacer public static final Parcelable.Creator> CREATOR porque MyParcelable no es estadístico.
El segundo era leer en un objeto Parcelable que usted necesita el acceso al ClassLoader
que no se puede conseguir de T
debido al borrado del tipo .
La clase de abajo es una adaptación de una clase que estoy utilizando en la producción que supera ambos problemas. Nota: No he probado específicamente esta clase, así que avísame si tienes algún problema.
public class TestModel<T extends Parcelable> implements Parcelable { private List<T> items; private String someField; public List<T> items() { return items; } public void setItems(List<T> newValue) { items = newValue; } public String someField() { return someField; } public void setSomeField(String newValue) { someField = newValue; } //region: Parcelable implementation public TestModel(Parcel in) { someField = in.readString(); int size = in.readInt(); if (size == 0) { items = null; } else { Class<?> type = (Class<?>) in.readSerializable(); items = new ArrayList<>(size); in.readList(items, type.getClassLoader()); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(someField); if (items == null || items.size() == 0) dest.writeInt(0); else { dest.writeInt(items.size()); final Class<?> objectsType = items.get(0).getClass(); dest.writeSerializable(objectsType); dest.writeList(items); } } public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() { public TestModel createFromParcel(Parcel in) { return new TestModel(in); } public TestModel[] newArray(int size) { return new TestModel[size]; } }; //endregion }
Sí tu puedes. Sólo tiene que almacenar el nombre de la clase o el cargador de clases durante la construcción de su objeto de subclase y luego puede pasarlo durante la operación de lectura / escritura del parcelable.
Instrucciones paso a paso:
Paso 1 . Almacene el nombre de la clase que se extiende desde su clase genérica de la siguiente manera:
public abstract class GenericClass<T> implements Parcelable { private String className;
Paso 2 . Cualquier clase que se extienda desde su clase genérica debe especificar el nombre de la clase durante su construcción como esto:
public class MyClass extends GenericClass<MyClass> { public MyClass () { super(); setClassName(MyClass.class.getName()); // Generic class setter method }
Paso 3 . En su clase genérica, puede leer / escribir sus nombres de clase a getClassLoader () así:
public abstract class GenericClass<T> implements Parcelable { private String className; T myGenericObject; protected MyClass (Parcel in) { super(in); this.className = in.readString(); ClassLoader classLoader; try { classLoader = Class.forName(this.className).getClassLoader(); } catch (ClassNotFoundException e) { e.printStackTrace(); } myGenericObject = in.readParcelable(classLoader); //... Other class members can go here } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeString(className); //... Other class members can go here }
}
Escriba el nombre de la clase de miembro genérico de datos en el paquete y luego vuelva a leerlo para crear su cargador de clases. Ejemplo,
public class MyClass<T> implements Parcelable { T data; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(data.getClass().getName()); dest.writeParcelable((Parcelable) data, 0); } private MyClass(Parcel in) { final String className = in.readString(); try { data = in.readParcelable(Class.forName(className).getClassLoader()); } catch (ClassNotFoundException e) { Log.e("readParcelable", className, e); } }
- Android: Estándares para prefijar archivos en el directorio RES aparte de ic_?
- Debe agregar un icono a su APK mientras carga la aplicación en Google Play