打包/解包自定义对象的 HashMap 的最佳方法是啥?
Posted
技术标签:
【中文标题】打包/解包自定义对象的 HashMap 的最佳方法是啥?【英文标题】:What's the best approach to parcel/unparcel a HashMap of custom objects?打包/解包自定义对象的 HashMap 的最佳方法是什么? 【发布时间】:2012-07-16 12:08:20 【问题描述】:我有一个 Event
类,它定义了一个私有 HashMap
,如下所示:
private Map<String, Object> data = new HashMap<String, Object>();
Event
类是为任何类型的“事件”包装的。这个HashMap
可以包含键引用的任何对象实例。接收Event
实例的类知道与每个键相关的类,因此它可以安全地将Object
转换为其对应的子类。
当我尝试在 2 个进程之间传递 Event
实例时出现问题。 Event
实现了Parcelable
,因此可以通过Message
发送:
Bundle bundle = new Bundle();
bundle.putParcelable(Event.BUNDLE_KEY, event);
// Make the message with the bundle
Message message = new Message();
message.setData(bundle);
解组时:
public void readFromParcel(Parcel in)
idEvent = in.readInt();
priority = in.readInt();
idSource = in.readInt();
idDestination = in.readInt();
action = in.readInt();
Bundle mapBundle = in.readBundle();
if (mapBundle.getSerializable(MAP_KEY) instanceof HashMap)
data = (Map<String, Object>) mapBundle.getSerializable(MAP_KEY);
else
Log.e(TAG, "Parcel reading error: not a HashMap");
问题是这不起作用,因为我需要指定mapBundle
使用哪个ClassLoader
,例如mapBundle.setClassLoader(Entity.class.getClassLoader());
。 但是我不知道Object
的子类HashMap
会有什么......
这是我的想法:
编写一个ClassLoader
来加载这些类中的任何一个。问题是我无法获得代表对象的byte[]
,因为它位于HashMap
内。而且我不能使用mapBundle.getSerializable()
来获取它,因为它会精确地抛出ClassNotFound
异常。
传递一些额外信息,以便我知道HashMap
上的课程。除了这看起来是多余的信息之外,仍然不行,因为如果我在 Bundle 上设置一个类加载器,它仍然会在其他类上抛出 ClassNotFound
异常......
我非常感谢在这个问题上提供一些帮助。提前致谢!
【问题讨论】:
hashmap中使用的类也应该实现Parcelable 确实如此。那不是问题。问题是 ClassNotFound,而不是 Parcelable 异常。 【参考方案1】:其实this 回答了我的问题。我必须获得对我的 ClassLoader 的引用,然后将其设置为反序列化,我认为这是通过另一个线程完成的,可能是系统线程,因此它不知道我的类。
【讨论】:
【参考方案2】:我认为最好的解决方案是重新考虑您的计划,以拥有对象的 hashmap 并根据 hashmap 中的键将它们转换为真实对象。
这样做你不会真正利用 java 为你提供的类型安全,而且你还会从 HashMap 中获得额外的开销。
我建议将 Event 作为接口实现,并让每种类型的 Event 实现该接口。
这样,类中的“数据”变量可以用描述性名称重命名(这使代码更易于阅读),并且您不必存储任何冗余数据。
【讨论】:
嗯...请记住,每个事件都可以有几个完全不同的属性。这也意味着需要在每个事件上实现 Parcelable。这也意味着如果以后设计新事件(这很可能),我必须创建这样的类,这将完全破坏向后兼容性。我也看到没有比data
更好的名字了,因为它就是:未知数据。 Event
类不关心里面有什么。
也许你可以编写一个包装器,在决定是否解包之前查看一个 Parcel,如果它得到一个带有 idEvent 的 Parcel,它在某种查找表中没有,那它丢弃了那个包裹?
决定拆包还是不拆包?为什么我要寄一些我不想拆包的东西?对不起,我没有关注你...问题是HashMap本身是可序列化的,当我想得到它时,它会抛出一个ClassNotFound异常,所以我什至无法得到我想要的Parcel......跨度>
抱歉不清楚,我的意思是如果程序的新版本向旧版本发送了一些东西,那么旧版本不知道如何处理该事件,需要忽略它。
但是你的方法就没那么简单了。例如,一个新事件将需要一个新类,但该类在旧版本中不可用。程序如何知道问题是加载类还是该类实际上不存在?以上是关于打包/解包自定义对象的 HashMap 的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章