2012-01-27 1 views
8

Necesito saber cómo hacer una clase interna Parcelable para que los objetos de su tipo puedan pasar a través de AIDL a un servicio remoto. No puedo encontrar ninguna información sobre esto.Cómo hacer una clase interna Parcelable

Aquí hay un código de ejemplo de lo que intento lograr, pero no se compila porque el CREADOR en la clase Bar no puede ser estático (es decir, porque está en una clase interna). No puedo hacer que Bar sea una clase interna estática y no puedo mover Bar fuera de la clase Foo (otras dependencias dentro del sistema). También necesito saber cómo haría referencia a la clase Bar desde dentro de un archivo AIDL. Cualquier ayuda es muy apreciada.

public class Foo implements Parcelable 
{ 
    private int a; 

    public Foo() 
    { 
    } 

    public Foo(Parcel source) 
    { 
     this.a = source.readInt(); 
    } 

    public int describeContents() 
    { 
     return 0; 
    } 

    public void writeToParcel(Parcel dest, int flags) 
    { 
     dest.writeInt(this.a); 
    } 

    public static final Parcelable.Creator<Foo> CREATOR 
    = new Parcelable.Creator<Foo>() 
    { 
     ... 
    } 

    public class Bar implements Parcelable 
    { 
     private int b; 

     public Bar() 
     { 
     } 

     public Bar(Parcel source) 
     { 
      this.b = source.readInt(); 
     } 

     public int describeContents() 
     { 
      return 0; 
     } 

     public void writeToParcel(Parcel dest, int flags) 
     { 
      dest.writeInt(this.b); 
     } 

     public static final Parcelable.Creator<Bar> CREATOR 
     = new Parcelable.Creator<Bar>() 
     { 
      ... 
     } 
    } 
} 
+0

Puede echar un vistazo a http://stackoverflow.com/questions/35923039/android-implementing-parcelable-inner-class esto le ayudará. – chaitanya

+0

Eche un vistazo a esta solución. Esto te ayudará a http://stackoverflow.com/questions/35923039/android-implementing-parcelable-inner-class – chaitanya

Respuesta

3

La respuesta es que una clase interna siempre se puede convertir en su propia clase. Cualquiera que sea la funcionalidad a la que la clase interna necesite acceder desde la instancia de la clase externa o viceversa, siempre se puede hacer a través de una interfaz o API pública. Intenta hacer Bar en su propia clase. Cualquier componente de Foo Bar que necesite acceso, proporcione pasando la instancia de Foo en Bar e implemente la API adecuada.

+0

Gracias por tu respuesta. Sí, esa sería la solución ideal. Sin embargo, tengo que interactuar con un código jni (para el cual no tengo el C++ para recompilar) que está esperando un Foo.Bar (y se bloquea si recibe una barra). – MichaelL

1

Si su clase externa mantiene una referencia a las instancias de clases internas que podría hacerlo de esta manera:

public class OuterClass implements Parcelable 
{ 
    private InnerClass reference; 

    protected OuterClass(Parcel source) 
    { 
     this.reference = new InnerClass(source); 
     // ... 
    } 

    @Override 
    public void writeToParcel(Parcel destination, int flags) 
    { 
     reference.writeToParcel(destination, flags); 
     // ... 
    } 

    public class InnerClass implements Parcelable 
    { 
     protected InnerClass(Parcel source) 
     { 
      // Read from your parcel. 
     } 

     @Override 
     public void writeToParcel(Parcel destination, int flags) 
     { 
      // Write to your parcel. 
     } 
    } 

    public static final Parcelable.Creator<OuterClass> CREATOR = new Creator<OuterClass>() 
    { 
     @Override 
     public OuterClass createFromParcel(Parcel source) 
     { 
      return new OuterClass(source); 
     } 

     @Override 
     public OuterClass[] newArray(int size) 
     { 
      return new OuterClass[size]; 
     } 
    } 
} 
8

Hace poco me encontré con el mismo problema y hacer que la clase interna estática trabajado en mi situación.

Leí sobre por qué esto realmente funcionaría y tiene más sentido para mí, así que pensé que lo compartiría. Una clase interna es una clase que está anidada dentro de otra clase y tiene una referencia a una instanciación de su clase contenedora. A través de esa referencia, puede acceder a los miembros de las clases contenedoras como si fuera la propia clase contenedora. Por lo tanto, está vinculado a una instancia de la clase contenedora y, por lo tanto, no puede tener miembros estáticos (ya que no estarían vinculados a la clase contenedora).

Declarar la clase anidada como estática la desacopla de una instancia de la clase contenedora, y por lo tanto puede tener sus propias variables estáticas (y cualquier otra cosa que pueda tener una clase normal). Por supuesto, no podrá acceder a los miembros de la clase contenedora.

+0

Declarar la clase interior parcelable como 'estática' me ha funcionado al usar clases parcelables anidadas. – Eido95

0

Su barra no tiene que ser empacable. Puede simplemente guardar los campos Bar junto con los campos Foo y restaurar todo el objeto en el método createFromParcel(Parcel).

He aquí algunos ejemplo de código anterior:

import android.os.Parcel; 
import android.os.Parcelable; 

public class Foo implements Parcelable { 
    private int mFooData = 0; 
    private Bar mBar; 

    public Foo() { 
    } 

    protected Foo(Parcel in) { 
     mFooData = in.readInt(); 

     // Reading Bar 
     int barData = in.readInt(); 
     mBar = new Bar(barData); 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeInt(mFooData); 

     // Writing Bar 
     dest.writeInt(mBar.getBarData()); 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    public static final Creator<Foo> CREATOR = new Creator<Foo>() { 
     @Override 
     public Foo createFromParcel(Parcel in) { 
      return new Foo(in); 
     } 

     @Override 
     public Foo[] newArray(int size) { 
      return new Foo[size]; 
     } 
    }; 

    public class Bar { 
     private int mBarData = 0; 

     public Bar(int barData) { 
      mBarData = barData; 
     } 

     public int getBarData() { 
      return mBarData; 
     } 

     public void setBarData(int mBarData) { 
      this.mBarData = mBarData; 
     } 
    } 
} 
Cuestiones relacionadas