简体   繁体   English

帮助通过 ArrayList 和 parcelable Activity

[英]Help with passing ArrayList and parcelable Activity

So I've been googling most of yesterday and last nite and just can't seem to wrap my head around how to pass an arraylist to a subactivity.所以我昨天和昨晚的大部分时间都在谷歌上搜索,但似乎无法理解如何将 arraylist 传递给子活动。 There are tons of examples and snippets passing primitive data types, but what I have is an arraylist of type address (address.java below).有大量传递原始数据类型的示例和片段,但我拥有的是地址类型的 arraylist(地址如下)。

I've found a lot of stuff on stackoverflow and around the web on this, but nothing that got a lot of attention except for one with a GeoPoint example.我在 stackoverflow 和 web 上发现了很多东西,但除了一个 GeoPoint 示例之外,没有什么引起很多关注。 Again, it looked to me like they just flattened the GeoPoint object into two integers and passed it in. I can't do that because my address class may expand to include integers, floats, whatever.再一次,在我看来,他们只是将 GeoPoint object 扁平化为两个整数并将其传入。我不能这样做,因为我的地址 class 可能会扩展到包括整数、浮点数等。 Right now, the test app below is only two strings for simplicity.现在,为了简单起见,下面的测试应用程序只有两个字符串。 I thought if I could get the parcelalbe stuff working with that, the rest could follow.我想如果我能得到parcelalbe的东西,rest 可能会紧随其后。

Can someone post a working example for an ArrayList of a non-primitive object, or perhaps add code below to make this work?有人可以为非原始 object 的 ArrayList 发布一个工作示例,或者在下面添加代码以使其工作吗?

UPDATE : code below is now working after replies/editing.更新:下面的代码现在在回复/编辑后工作。 Thanks!谢谢!

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

    }

}

I can see a number of problems here:我可以在这里看到一些问题:

  1. Why use addressParcelable?为什么使用 addressParcelable? Why not make address implement Parcelable, and then use:为什么不让地址实现 Parcelable,然后使用:

     intent.putParcelableArrayListExtra( "addresses", addyExtras );
  2. Your parcelable object must include a static CREATOR.您的可包裹 object 必须包含 static CREATOR。 See the documentation for details.有关详细信息,请参阅文档

  3. You are not actually adding any extras to the intent before you call startActivity() .在调用startActivity()之前,您实际上并没有向意图添加任何额外内容。 See point 1 for a suggestion here.有关建议,请参见第 1 点。

I think that you will need to address all of these issues in order to get it working.我认为您需要解决所有这些问题才能使其正常工作。

It can be done MUCH simpler, without all the pain-in-the-ass of implementing Parcelable ... ArrayList (but NOT any List ) is Serializable .它可以做得更简单,没有实现Parcelable的所有痛苦...... ArrayList (但不是任何List )是Serializable So, you can put the entire list using putExtra() and retrieve it using getSerializableExtra() , as Sam said.因此,正如 Sam 所说,您可以使用 putExtra() 放置整个列表并使用getSerializableExtra() putExtra()检索它。

BUT, I want to add one more important thing: the object your array list stores has to also implement Serializable ... and all other complex objects that the object may contain (in your case none) must also implement that (so it's recursive - in order to serialize an object, you must be able to serialize all of its fields).但是,我想添加一件更重要的事情:您的数组列表存储的 object 还必须实现Serializable ......以及 object 可能包含的所有其他复杂对象(在您的情况下没有)也必须实现它(所以它是递归的 -为了序列化 object,您必须能够序列化其所有字段)。

Now, you might be asking yourself why implementing Serializable instead of Parcelable when there are already methods for reading and writing array lists of parcelables?现在,您可能会问自己,既然已经有了读写 parcelable 数组列表的方法,为什么还要实现Serializable而不是Parcelable Well... the difference is simplicity - just add implements Serializable and optionally private static final long serialVersionUID = SOME_CONSTANT and you're DONE!嗯......不同之处在于简单 - 只需添加implements Serializable和可选private static final long serialVersionUID = SOME_CONSTANT ,你就完成了! That is the reason why I never use Parcelable - you can do all those things using Serializable with literally 2 lines of code - instead of many method inheritances and all that stuff...这就是我从不使用Parcelable的原因——你可以使用Serializable用字面上的 2 行代码来做所有这些事情——而不是许多方法继承和所有那些东西......

You can pass Serializable objects via putExtra.您可以通过 putExtra 传递 Serializable 对象。 ArrayList implements Serializable. ArrayList 实现了可序列化。

Mike dg is correct!迈克 dg 是正确的!

putExtra() and getSerializable() will store and retrieve an ArrayList<> of your custom objects, with no interface implementing required. putExtra()getSerializable()将存储和检索自定义对象的ArrayList<> ,无需实现接口。 Worked for me!为我工作!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM