帮助传递 ArrayList 和可传递对象 Activity

32
所以我昨天和昨晚大部分时间都在谷歌搜索,但似乎无法理解如何将一个arraylist传递给子活动。 有很多例子和片段传递原始数据类型,但我有一个类型为address.java的arraylist。
我在stackoverflow和网络上找到了很多相关信息,但除了一个带有GeoPoint示例的问题外,没有得到太多关注。 同样,对我来说,它看起来像他们只是将GeoPoint对象展平成两个整数并将其传递。 我不能这样做,因为我的address类可能会扩展到包括整数,浮点数等。 现在,测试应用程序仅使用两个字符串以简化操作。 我认为,如果我可以让parcelalbe的东西与此一起工作,其他部分也可以跟随。
请问有人能发一个ArrayList非原始对象的工作示例,或者可以添加下面的代码使其工作?
更新:在回复/编辑后,下面的代码现在正在工作。 谢谢!
/* 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 ());
       }

    }

}

太棒了!!!!!!!做得很好,这是我第一次使用它。谢谢。 - Selim Raza
4个回答

24

我在这里看到了一些问题:

  1. 为什么要使用addressParcelable?为什么不让address实现Parcelable,然后使用:

    intent.putParcelableArrayListExtra( "addresses", addyExtras );
    
  2. 你的 Parcelable 对象必须包含一个静态的 CREATOR。请参阅 文档 了解详情。

  3. 在调用 startActivity() 之前,你实际上没有向 intent 中添加任何额外的内容。建议参考第1点。

  4. 我认为你需要解决所有这些问题才能让它正常工作。


有一段时间,我认为我需要一个额外的类(实现Parcelable)来转换整个对象。我想这就是addressParcelable的来源。我已经从上面的代码中删除了它。我已经按照您的建议进行了实现,尽管可能不正确。你有时间的时候能看一下吗?我现在正在试图追踪subActivity()中的空指针错误。 - wufoo
3
我认为你需要调用getIntent().getParcelableArrayList("mylist"),而不是savedInstanceState.getParcelableArrayList("mylist")。 - Mark Allison
你的意思是使用getParcelableArrayListExtra()吗?我尝试过了,但是出现了一个新的错误(请参见上面新编辑的代码)。 - wufoo
我觉得现在它可以工作了!上面的代码已经被编辑 - 必须修改地址类中的构造函数。 - wufoo
做得好,你成功让它工作了。我认为你可以放弃 addyExtras,只需使用 intent.putParcelableArrayListExtra("mylist", myList); - 这将节省你遍历列表的时间。 - NickT

8
它可以更简单地完成,而无需实现Parcelable的所有痛苦... ArrayList(但不是任何List)是Serializable的。因此,您可以使用putExtra()来放置整个列表,并使用getSerializableExtra()检索它,就像Sam所说的那样。
但是,我想再添加一件重要的事情:您的数组列表存储的对象也必须实现Serializable...以及对象可能包含的所有其他复杂对象(在您的情况下为零),这些对象也必须实现该对象(因此它是递归的——为了序列化一个对象,您必须能够序列化其所有字段)。
现在,您可能会问自己为什么要实现Serializable而不是Parcelable,当已经有用于读写parcelable数组列表的方法时? 好吧......区别在于简单性——只需添加implements Serializable和可选的private static final long serialVersionUID = SOME_CONSTANT,您就完成了!这就是我从不使用Parcelable的原因——您可以使用Serializable用仅两行代码(而不是许多方法继承和所有那些东西)完成所有这些事情...

6
与Serializable相比,Parcelable的优点在于它速度更快,如果你的列表很大,差异会很明显。 - nicopico

6

您可以通过putExtra传递Serializable对象。ArrayList实现了Serializable接口。


非常有帮助。谢谢你。你会认为它会更明显。 - Riot Goes Woof

6

Mike dg是正确的!

putExtra()getSerializable()将存储和检索一个ArrayList<>,里面包含你自定义的对象,不需要实现接口。对我有用!


1
抱歉,我错了..你的对象必须实现Serializable接口..但是在那之后它可以工作.. - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接