【问题标题】:Help with passing ArrayList and parcelable Activity帮助传递 ArrayList 和 parcelable Activity
【发布时间】:2011-04-28 13:17:16
【问题描述】:

所以我昨天和昨晚的大部分时间都在谷歌搜索,但似乎无法理解如何将数组列表传递给子活动。有大量示例和 sn-ps 传递 primitive 数据类型,但我拥有的是一个 address 类型的数组列表(下面的 address.java)。

我在 stackoverflow 和网络上找到了很多关于这方面的内容,但除了一个 GeoPoint 示例之外,没有什么能引起很多关注。再一次,在我看来,他们只是将 GeoPoint 对象扁平化为两个整数并将其传入。我不能这样做,因为我的地址类可能会扩展为包括整数、浮点数等。现在,为了简单起见,下面的测试应用程序只有两个字符串。我想如果我能让 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 ());
       }

    }

}

【问题讨论】:

  • 太棒了!!!!!!!!!!!!!很好用,我第一次使用它。谢谢sss

标签: android android-activity parcelable


【解决方案1】:

我可以在这里看到一些问题:

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

    intent.putParcelableArrayListExtra( "addresses", addyExtras );
    
  2. 您的 parcelable 对象必须包含一个静态 CREATOR。详情请参阅documentation

  3. 在调用 startActivity() 之前,您实际上并没有在意图中添加任何额外内容。在此处查看第 1 点的建议。

我认为您需要解决所有这些问题才能使其正常工作。

【讨论】:

  • 有一次,我认为我需要一个额外的类(实现 Parcelable)来转换整个对象。我认为这就是 addressParcelable 的来源。我已经从上面的代码中删除了它。我已经实施了您的建议,尽管可能不正确。有时间你会去看吗?在我正在尝试寻找的 subActivity() 中出现空指针错误。
  • 我认为你需要调用getIntent().getParcelableArrayList("mylist"),而不是saveInstanceState.getParcelableArrayList("mylist");
  • 你的意思是getParcelableArrayListExtra()吗?尝试过,但出现新错误(请参阅上面新编辑的代码)。
  • :) 我认为它现在可以工作了!上面编辑的代码 - 必须修改地址类中的构造函数
  • 很好地让它工作。我认为您可以省去 addyExtras 并只使用 intent.putParcelableArrayListExtra ("mylist", myList); - 这样可以节省您对列表的迭代
【解决方案2】:

它可以做得更简单,没有实现Parcelable的所有痛苦。 ArrayList(但不是任何List)是Serializable。因此,正如 Sam 所说,您可以使用 putExtra() 放置整个列表并使用 getSerializableExtra() 检索它。

但是,我想补充一件更重要的事情:您的数组列表存储的对象还必须实现 Serializable... 并且该对象可能包含的所有其他复杂对象(在您的情况下没有)也必须实现(所以它是递归的——为了序列化一个对象,你必须能够序列化它的所有字段)。

现在,您可能会问自己,既然已经有了读写parcelables 数组列表的方法,为什么还要实现Serializable 而不是Parcelable? 嗯......不同之处在于简单 - 只需添加implements Serializable 和可选的private static final long serialVersionUID = SOME_CONSTANT,您就完成了!这就是为什么我从不使用 Parcelable 的原因——你可以使用 Serializable 用字面上的 2 行代码来做所有这些事情——而不是许多方法继承和所有这些东西......

【讨论】:

【解决方案3】:

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

【讨论】:

  • 巨大的帮助。谢谢你。你会认为它会变得更加明显。
【解决方案4】:

Mike dg 是正确的!

putExtra()getSerializable() 将存储和检索自定义对象的ArrayList&lt;&gt;,无需实现接口。为我工作!

【讨论】:

  • 对不起,我错了..你的对象必须实现 Serializable.. 但之后它就可以工作了..
猜你喜欢
  • 2017-08-07
  • 2012-06-12
  • 2019-07-30
  • 1970-01-01
  • 2017-01-25
  • 2021-02-10
  • 1970-01-01
  • 2018-10-02
  • 2017-07-27
相关资源
最近更新 更多