打包/解包自定义对象的 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 的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

qt中如何解包利用python 的struct.pack()函数打包的数据

在 Python 中打包/解包复杂数据

ckeditor 表情包自定义

获取 Perl 打包/解包模板的元素数量

Wolf RPG Editor之 解包与打包

压缩/打包/解包 命令详解