Ayuda con la aprobación de ArrayList y la actividad parcelable


Así que he estado buscando en Google la mayor parte de ayer y última noche y parece que no puedo envolver mi cabeza alrededor de cómo pasar un arraylist a una subactividad. Hay toneladas de ejemplos y fragmentos que pasan tipos de datos primitivos, pero lo que tengo es una arraylist de tipo address (address.java a continuación).

He encontrado muchas cosas en stackoverflow y alrededor de la web sobre esto, pero nada que haya recibido mucha atención excepto uno con un ejemplo de punto geográfico. De nuevo, me pareció como si simplemente aplanaran el objeto GeoPoint en dos enteros y lo pasaran. No puedo hacer eso porque mi clase de dirección puede expandirse para incluir enteros, flotadores, lo que sea. En este momento, la aplicación de prueba a continuación es solo dos cadenas para simplificar. Pensé que si conseguía que las cosas de Parcelalbe funcionaran con eso, el resto podría seguir.

¿Puede alguien publicar un ejemplo de trabajo para una ArrayList de un objeto no primitivo, o tal vez agregar código a continuación para hacer que esto funcione?

ACTUALIZACIÓN: código a continuación ahora está trabajando después de respuestas / edición. ¡Gracias!

/* helloParcel.java */        
       public class helloParcel extends Activity
{
    // holds objects of type 'address' == name and state
    private ArrayList <address> myList;

    @Override
    public void onCreate (Bundle savedInstanceState)
    {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.main);

        Button b1 = (Button) findViewById(R.id.button1);
        b1.setOnClickListener(ocl);

        myList = new ArrayList();
        address frank   = new address ("frank", "florida");
        address mary    = new address ("mary", "maryland");
        address monty   = new address ("monty", "montana");

        myList.add (frank);
        myList.add (mary);
        myList.add (monty);

        // add the myList ArrayList() the the extras for the intent

    }

    OnClickListener ocl = new OnClickListener() 
    {

        @Override
        public void onClick(View v) 
        {
            // fill parceable and launch activity
            Intent intent = new Intent().setClass(getBaseContext (), subActivity.class);

            // for some reason, I remember a posting saying it's best to create a new
            // object to pass.  I have no idea why..
            ArrayList <address> addyExtras = new ArrayList <address>();

            for (int i = 0; i < myList.size(); i++)
                addyExtras.add (myList.get(i));

            intent.putParcelableArrayListExtra ("mylist", addyExtras);
            startActivity(intent);
        }
    };
} 



/* address.java */
  public class address implements Parcelable
{
    private String name;
    private String state;
    private static String TAG = "** address **";

    public address (String n, String s)
    {
        name = n;
        state = s;
        Log.d (TAG, "new address");
    }

    public address (Parcel in)
   {
    Log.d (TAG, "parcel in");
        name = in.readString ();
        state = in.readString ();
   }

    public String getState ()
    {
        Log.d (TAG, "getState()");
        return (state);
    }

    public String getName ()
    {
        Log.d (TAG, "getName()");
        return (name);
    }

    public static final Parcelable.Creator<address> CREATOR
    = new Parcelable.Creator<address>() 
   {
         public address createFromParcel(Parcel in) 
         {
            Log.d (TAG, "createFromParcel()");
             return new address(in);
         }

         public address[] newArray (int size) 
         {
            Log.d (TAG, "createFromParcel() newArray ");
             return new address[size];
         }
    };

    @Override
   public int describeContents ()
   {
        Log.d (TAG, "describe()");
       return 0;
   }

    @Override
   public void writeToParcel (Parcel dest, int flags)
   {
        Log.d (TAG, "writeToParcel");
       dest.writeString (name);
       dest.writeString (state);
   }

}


/* subActivity.java */
  public class subActivity extends Activity
{
    private final String TAG = "** subActivity **";
    private ArrayList <address> myList;

    @Override
    protected void onCreate (Bundle savedInstanceState)
    {
       super.onCreate (savedInstanceState);
       Log.d (TAG, "onCreate() in subActivity");

       setContentView(R.layout.subactivity);
       TextView tv1 = (TextView) findViewById(R.id.tv_sub);

       myList = getIntent().getParcelableArrayListExtra ("mylist");
       Log.d (TAG, "got myList");

       for (int i = 0; i < myList.size (); i++)
       {
        address a = myList.get (i);
        Log.d (TAG, "state:" + a.getState ());
        tv1.setText (a.getName () + " is from " + a.getState ());
       }

    }

}
Author: wufoo, 2011-04-28

4 answers

Puedo ver una serie de problemas aquí:

  1. ¿Por qué usar addressParcelable? ¿Por qué no hacer que address implement sea parcelable, y luego usar:

    intent.putParcelableArrayListExtra( "addresses", addyExtras );
    
  2. El objeto parcelable debe incluir un CREADOR estático. Véase la documentación para más detalles.

  3. En realidad, no está agregando ningún extra a la intent antes de llamar startActivity(). Véase aquí una sugerencia en el punto 1.

Creo que usted tendrá que abordar todos estos temas en para que funcione.

 23
Author: Mark Allison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-13 11:48:25

Se puede hacer mucho más simple, sin todo el dolor en el culo de implementar Parcelable... ArrayList (pero NO cualquier List) es Serializable. Por lo tanto, puede poner toda la lista usando putExtra() y recuperarla usando getSerializableExtra(), como dijo Sam.

PERO, quiero agregar una cosa más importante: el objeto que almacena su lista de matrices también debe implementar Serializable... y todos los demás objetos complejos que el objeto pueda contener (en su caso ninguno) también deben implementarlo (por lo que es recursivo, para serializar un objeto, usted debe ser capaz de serializar todos sus campos).

Ahora, usted podría preguntarse por qué implementar Serializable en lugar de Parcelable cuando ya hay métodos para leer y escribir listas de matrices de parcelables? Bien... la diferencia es la simplicidad-basta con añadir implements Serializable y opcionalmente private static final long serialVersionUID = SOME_CONSTANT y ya está! Esa es la razón por la que nunca uso Parcelable - puedes hacer todas esas cosas usando Serializable con literalmente 2 líneas de código - en lugar de muchas herencias de métodos y todas esas cosas...

 8
Author: Dexter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-15 21:53:11

Puede pasar objetos serializables a través de putExtra. ArrayList implementa Serializable.

 6
Author: Mike dg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-28 13:21:02

Mike dg es correcto!

putExtra() y getSerializable() almacenará y recuperará un ArrayList<> de sus objetos personalizados, sin necesidad de implementar una interfaz. ¡Funcionó para mí!

 6
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-22 09:55:27