LinkedList的投入额外的意向被改写的下一个活动时,检索到ArrayList中 [英] LinkedList put into Intent extra gets recast to ArrayList when retrieving in next activity
问题描述
一个行为我正在观察WRT传递序列化的数据作为额外的意图是很奇怪的,我只是想澄清是否有什么东西我不会错过了。
A behaviour i'm observing w.r.t passing serializable data as intent extra is quite strange, and I just wanted to clarify whether there's something I'm not missing out on.
于是事情,我试图做的是,在 ActivtyA
我把的LinkedList
实例到意图
我启动下一个活动创建 - ActivityB
So the thing I was trying to do is that in ActivtyA
I put a LinkedList
instance into the intent
I created for starting the next activity - ActivityB
.
LinkedList<Item> items = (some operation);
Intent intent = new Intent(this, ActivityB.class);
intent.putExtra(AppConstants.KEY_ITEMS, items);
在的onCreate
ActivityB
中,我试图找回的LinkedList
额外如下 -
In the onCreate
of ActivityB
, I tried to retrieve the LinkedList
extra as follows -
LinkedList<Item> items = (LinkedList<Item>) getIntent()
.getSerializableExtra(AppConstants.KEY_ITEMS);
在运行此,我多次得到了 ClassCastException异常
在 ActivityB
,在该行以上。基本上,除了说我收到的ArrayList
。有一次,我改变了code以上,以接收的ArrayList
代替,一切工作就好了。
On running this, I repeatedly got a ClassCastException
in ActivityB
, at the line above. Basically, the exception said that I was receiving an ArrayList
. Once I changed the code above to receive an ArrayList
instead, everything worked just fine.
现在我不能只从现有的文件弄清楚这是否通过序列化List实现的时候是在Android上预期的行为。或许,有一些根本性错误瓦特/我在做什么。
Now I can't just figure out from the existing documentation whether this is the expected behaviour on Android when passing serializable List implementations. Or perhaps, there's something fundamentally wrong w/ what I'm doing.
感谢。
推荐答案
我可以告诉你为什么会这样,但你不会喜欢它, - )
I can tell you why this is happening, but you aren't going to like it ;-)
首先一点背景资料:
其他在意图
基本上是一个Android 捆绑
这基本上是一个< code键/值对>的HashMap 。所以,当你做这样的事情
Extras in an Intent
are basically an Android Bundle
which is basically a HashMap
of key/value pairs. So when you do something like
intent.putExtra(AppConstants.KEY_ITEMS, items);
安卓创建一个新的捆绑
的群众演员,并增加了一个映射条目到捆绑
,其中最关键的是 AppConstants.KEY_ITEMS
和值项(这是你的LinkedList对象)。
Android creates a new Bundle
for the extras and adds a map entry to the Bundle
where the key is AppConstants.KEY_ITEMS
and the value is items (which is your LinkedList object).
这是一切优秀和良好的,以后你的code。如果你看演员捆绑执行您会发现它包含了一个的LinkedList
。现在到了有趣的部分...
This is all fine and good, and if you were to look at the extras bundle after your code executes you will find that it contains a LinkedList
. Now comes the interesting part...
当你调用 startActivity()
与含额外意图,机器人需要的额外转换键/值对映射成一个字节流。基本上,它需要为序列化的捆绑。它需要做,因为它可能会开始活动的另一个进程中,为了做到这点,需要序列化/反序列化被捆绑的对象,以便它可以重新创建新进程。它也需要这样做是因为机器人保存意图的内容在某些系统表,以便它可以再生意图是否需要购买。
When you call startActivity()
with the extras-containing Intent, Android needs to convert the extras from a map of key/value pairs into a byte stream. Basically it needs to serialize the Bundle. It needs to do that because it may start the activity in another process and in order to do that it needs to serialize/deserialize the objects in the Bundle so that it can recreate them in the new process. It also needs to do this because Android saves the contents of the Intent in some system tables so that it can regenerate the Intent if it needs to later.
为了给捆绑
序列化为字节流,它通过被捆绑的地图,并得到每个键/值对。然后它拍摄的价值(这是某种对象),并试图确定它是哪种对象,以便它可以以最有效的方式把它序列。要做到这一点,它会针对众所周知的对象类型的列表中选择对象类型。 已知的对象类型列表中包含像整数
,龙
,字符串
,地图
,捆绑
不幸的是还列表
。因此,如果对象是一个列表
(其中有许多不同种类,其中包括的LinkedList
)将其序列,并标记这类型的对象列表
。
In order to serialize the Bundle
into a byte stream, it goes through the map in the bundle and gets each key/value pair. Then it takes each "value" (which is some kind of object) and tries to determine what kind of object it is so that it can serialize it in the most efficient way. To do this, it checks the object type against a list of known object types. The list of "known object types" contains things like Integer
, Long
, String
, Map
, Bundle
and unfortunately also List
. So if the object is a List
(of which there are many different kinds, including LinkedList
) it serializes it and marks it as an object of type List
.
在捆绑
进行反序列化,即:当你做到这一点:
When the Bundle
is deserialized, ie: when you do this:
LinkedList<Item> items = (LinkedList<Item>)
getIntent().getSerializableExtra(AppConstants.KEY_ITEMS);
它会产生一个的ArrayList
为捆绑
类型列表中的所有对象
。
确实没有什么可以做改变Android的这种行为。至少现在你知道它为什么做这个。
There isn't really anything you can do to change this behaviour of Android. At least now you know why it does this.
只是让你知道:其实我写了一个小的测试程序来验证这种行为,我已经看过源$ C $下 Parcel.writeValue(宾语)
这是被从捆绑
时,地图上成字节流的转换。调用的方法
Just so that you know: I actually wrote a small test program to verify this behaviour and I have looked at the source code for Parcel.writeValue(Object v)
which is the method that gets called from Bundle
when it converts the map into a byte stream.
重要提示:由于列表
是一个接口,这意味着任何类实现列表
您放入捆绑
将出来作为一个的ArrayList
。
这也是有趣的是,地图
也是已知的对象类型,这意味着,无论是哪一种地图$ C $名单C>对象,你把一个
捆绑
(例如 TreeMap的
,的SortedMap
,或实现地图
接口的任何类),你总是会得到一个的HashMap
出来。
Important Note: Since List
is an interface this means that any class that implements List
that you put into a Bundle
will come out as an ArrayList
.
It is also interesting that Map
is also in the list of "known object types" which means that no matter what kind of Map
object you put into a Bundle
(for example TreeMap
, SortedMap
, or any class that implements the Map
interface), you will always get a HashMap
out of it.
这篇关于LinkedList的投入额外的意向被改写的下一个活动时,检索到ArrayList中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!