web-dev-qa-db-fra.com

Aide pour passer ArrayList et l'activité parcelable

J'ai donc fait des recherches sur Google la plupart de la journée d'hier et de la dernière nuit et je n'arrive pas à comprendre comment passer d'un arraylist à une sous-activité. Il y a des tonnes d'exemples et d'extraits passant primitifs types de données, mais ce que j'ai est une liste de type adresse (adresse. Java ci-dessous).

J'ai trouvé beaucoup de choses sur stackoverflow et sur le Web à ce sujet, mais rien qui a attiré beaucoup d'attention, sauf un avec un exemple GeoPoint. Encore une fois, il m'a semblé qu'ils venaient d'aplatir l'objet GeoPoint en deux entiers et de le transmettre. Je ne peux pas le faire car ma classe d'adresses peut s'étendre pour inclure des entiers, des flottants, peu importe. Pour le moment, l'application de test ci-dessous n'est que deux chaînes pour plus de simplicité. J'ai pensé que si je pouvais faire fonctionner les trucs de colis avec ça, le reste pourrait suivre.

Quelqu'un peut-il publier un exemple de travail pour une liste de tableaux d'un objet non primitif, ou peut-être ajouter du code ci-dessous pour que cela fonctionne?

MISE À JOUR : le code ci-dessous fonctionne maintenant après les réponses/l'édition. Merci!

/* 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 ());
       }

    }

}
31
wufoo

Je peux voir un certain nombre de problèmes ici:

  1. Pourquoi utiliser addressParcelable? Pourquoi ne pas faire implémenter l'adresse Parcelable, puis utiliser:

    intent.putParcelableArrayListExtra( "addresses", addyExtras );
    
  2. Votre objet parcellable doit inclure un CRÉATEUR statique. Voir documentation pour plus de détails.

  3. Vous n'ajoutez en fait aucun extras à l'intention avant d'appeler startActivity(). Voir le point 1 pour une suggestion ici.

Je pense que vous devrez résoudre tous ces problèmes afin de le faire fonctionner.

23
Mark Allison

Cela peut être BEAUCOUP plus simple, sans toute la peine d'implémenter Parcelable... ArrayList (mais PAS tout List) est Serializable. Ainsi, vous pouvez mettre la liste entière en utilisant putExtra() et la récupérer en utilisant getSerializableExtra(), comme l'a dit Sam.

MAIS, je veux ajouter une chose plus importante: l'objet que votre liste de tableaux stocke doit également implémenter Serializable... et tous les autres objets complexes que l'objet peut contenir (dans votre cas aucun) doivent également implémenter cela (donc c'est récursif - pour sérialiser un objet, vous devez être capable de sérialiser tous ses champs).

Maintenant, vous vous demandez peut-être pourquoi implémenter Serializable au lieu de Parcelable alors qu'il existe déjà des méthodes pour lire et écrire des listes de tableaux de parcelables? Eh bien ... la différence est la simplicité - il suffit d'ajouter implements Serializable et éventuellement private static final long serialVersionUID = SOME_CONSTANT et tu as fini! C'est la raison pour laquelle je n'utilise jamais Parcelable - vous pouvez faire toutes ces choses en utilisant Serializable avec littéralement 2 lignes de code - au lieu de nombreux héritages de méthode et tout ça ...

8
Dexter

Mike dg a raison!

putExtra() et getSerializable() stockera et récupérera un ArrayList<> de vos objets personnalisés, sans implémentation d'interface requise. A travaillé pour moi!

6
Sam

Vous pouvez passer des objets sérialisables via putExtra. ArrayList implémente Serializable.

6
Mike dg