帮助传递 ArrayList 和 Parcelable Activity
因此,我昨天和昨晚的大部分时间都在谷歌上搜索,但似乎无法理解如何将数组列表传递给子活动。有大量传递原始数据类型的示例和片段,但我拥有的是address类型的数组列表(下面是address.java)。
我在 stackoverflow 和网络上找到了很多与此相关的内容,但除了一个包含 GeoPoint 示例的内容外,没有什么引起了很多关注。同样,在我看来,他们只是将 GeoPoint 对象展平为两个整数并将其传入。我不能这样做,因为我的地址类可能会扩展为包括整数、浮点数等。现在,为了简单起见,下面的测试应用程序只有两个字符串。我想如果我能让那些重要的东西与它一起工作,那么剩下的事情就可以随之而来。
有人可以发布一个非原始对象的 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 ());
}
}
}
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. There are tons of examples and snippets passing primitive data types, but what I have is an arraylist of type address (address.java below).
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. 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. 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.
Can someone post a working example for an ArrayList of a non-primitive object, or perhaps add code below to make this work?
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 ());
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我在这里可以看到很多问题:
为什么使用addressParcelable?为什么不让地址实现Parcelable,然后使用:
你的parcelable对象必须包含一个静态CREATOR。有关详细信息,请参阅文档。
在调用
startActivity()
之前,您实际上并未向意图添加任何额外内容。请参阅此处的第 1 点获取建议。我认为您需要解决所有这些问题才能使其发挥作用。
I can see a number of problems here:
Why use addressParcelable? Why not make address implement Parcelable, and then use:
Your parcelable object must include a static CREATOR. See the documentation for details.
You are not actually adding any extras to the intent before you call
startActivity()
. See point 1 for a suggestion here.I think that you will need to address all of these issues in order to get it working.
它可以更简单地完成,无需实现
Parcelable
的所有痛苦......ArrayList
(但不是任何List
)是可序列化
。因此,您可以使用putExtra()
放置整个列表,并使用getSerializedExtra()
检索它,正如 Sam 所说。但是,我想添加一件更重要的事情:您的数组列表存储的对象也必须实现
Serialized
...并且该对象可能包含的所有其他复杂对象(在您的情况下没有)也必须实现实现它(所以它是递归的 - 为了序列化一个对象,您必须能够序列化它的所有字段)。现在,您可能会问自己,当已经有读取和写入 Parcelable 数组列表的方法时,为什么要实现
Serialized
而不是Parcelable
呢?嗯...区别很简单 - 只需添加
implements Serialized
和可选的private static Final long serialVersionUID = SOME_CONSTANT
即可完成!这就是为什么我从不使用 Parcelable 的原因 - 你可以使用Serialized
完成所有这些事情,只需 2 行代码 - 而不是许多方法继承和所有这些东西。 。It can be done MUCH simpler, without all the pain-in-the-ass of implementing
Parcelable
...ArrayList
(but NOT anyList
) isSerializable
. So, you can put the entire list usingputExtra()
and retrieve it usinggetSerializableExtra()
, as Sam said.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).Now, you might be asking yourself why implementing
Serializable
instead ofParcelable
when there are already methods for reading and writing array lists of parcelables?Well... the difference is simplicity - just add
implements Serializable
and optionallyprivate static final long serialVersionUID = SOME_CONSTANT
and you're DONE! That is the reason why I never useParcelable
- you can do all those things usingSerializable
with literally 2 lines of code - instead of many method inheritances and all that stuff...您可以通过 putExtra 传递可序列化对象。 ArrayList 实现了可序列化。
You can pass Serializable objects via putExtra. ArrayList implements Serializable.
迈克 dg 是正确的!
putExtra()
和getSerialized()
将存储和检索自定义对象的ArrayList
,无需实现任何接口。为我工作!Mike dg is correct!
putExtra()
andgetSerializable()
will store and retrieve anArrayList<>
of your custom objects, with no interface implementing required. Worked for me!