不使用实现Serializable或Parcelable来传递Intent中的对象引用

13
我知道类似的问题已经被问了很多次。我认为我读过大部分。但是没有一个答案是适用的。
我需要通过Intents(活动调用/广播)传递复杂的对象。所有的操作都在我的进程内完成。这就是为什么我认为没有理由将我的对象写入流中,然后在几毫秒后重新组装它们。我想通过我的应用程序传递我的对象引用。有没有办法做到这一点?
由于我的应用程序将多次广播相同的事件,我不能依赖静态成员。我需要获取完全相同的对象进行广播。
这就是为什么我在考虑一个静态的“Referenceholder”,它将接受一个对象并返回一个整数,该整数标识其内部列表中的此对象,以便我可以通过".putExtras"传递这个整数。但据我所知,由于多个侦听器可能对同一个对象感兴趣,因此我无法从该列表中清除此对象,我必须永远将其保留在我的Referenceholder中(假设线程可能随时恢复-即使是2分钟之后)。
有任何想法吗?我做错了什么吗?或者有任何关于如何清理我的引用的想法(可能在几秒钟后?这可能会导致崩溃,但似乎比编写没有理由地组装和重组我的对象的代码更实际)。
2个回答

8
你的选择非常明确:在Intent中没有办法传递一个不可解组合的对象(Parcelable,Serializable)。就是这样。
你可能能做的是传递一个对不可解组合对象的引用。思路是传递一个键到映射该键到你想要传递的值的地图。如果Intent发送者和接收者都可以访问该地图,则可以通信到不可解组合对象的引用。
我不太明白你为什么认为静态成员不是你想要的。我猜测,在自定义应用程序对象中使用静态地图将是你想要的。...而且我怀疑,从你关于WeakHashMaps的评论中,你已经发现了这一点。
...除非你迄今为止没有解释为什么要使你的地图弱化。在使用弱映射之前,请查看软引用,以确保这不是你的意思。
祝好运

有些人在类似的问题中建议使用应用程序对象中的静态字段来传递所需的对象本身。这不是我想要的。静态WeakHashMap是完全合法的。如果每个引用都已清除,我将永远不需要该对象,因此WeakReference正是我所需要的。 - Chris
1
@Chris,很抱歉我不明白为什么你不能使用静态变量来在活动之间传递对象引用。如果ActivityA执行 Globals.object = objectIWantToPass;,然后ActivityB.onCreate() 执行 Object myObject = Globals.object; Globals.object = null;,这里不存在内存泄漏的危险。 - David Wasser
3
因为这是一个糟糕的解决方案。这就像你为什么要通过引用而不是类的静态成员来传递对象一样。我认为一个活动就像是一个处理我传入数据并最终会返回一些数据给调用者的函数。但看起来这是唯一的方法...... - Chris
1
@Chris:请注意,如果您使用弱映射,并且对象的唯一“引用”是您在意图中传递的映射键,则 GC 可能会在您传递对象时收集它。...我不明白为什么您认为应用程序中的静态变量是“可怕”的。 - G. Blake Meike
3
@G.BlakeMeike因为全局状态被认为是不良设计而感到可怕吗? - Jose_GD
显示剩余3条评论

4

编辑:

忘记这个解决方案吧。它不起作用。Android正在复制你在.startActivity()中传递的Intent。没有办法在活动内部获得任何引用。在我看来,这是谷歌的伟大bu****t。您必须调用您的activity并将对象的引用放置在静态成员中...

正如G. Blake Meike所提到的,Android没有通过Intents传递对象引用的方法。但是您可能可以使用WeakReferences

这个主题的一个非常优秀的文章可以在这里找到:http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

我通过这个问题找到了那个解决方案:Is it possible to get the object reference count?

所以我基本上要做的是: 我将使用Intents作为WeakHashMap的键,并将我的Object作为值传递。这似乎是唯一适合作为键的对象,因为您放入Intents额外内容的所有内容都将被序列化。由于这样,您每个Intent仅能传递一个对象。您可以在Activity中实现子类来保存您的对象,并将此子类放入映射中。但是我仍然不确定接收器将获得与调用者创建的Intent对象是否相同,但我认为是这样。如果它不是,我将编辑此解决方案(或者也许有人可以澄清一下)。


2
我不是Android专家,但我怀疑WeakReference不会起作用。 Serializable / Parcelable的要求意味着有一个根本的基础要求,即对象从一个地方深度复制到另一个地方。 这意味着任何形式的引用传递都不起作用;例如,因为我们正在谈论不同的内存地址空间。 即使它确实起作用,理由也必须是在应用程序实例之间共享引用对其他原因不利。 - Stephen C
你是对的。我测试过了。一个活动接收到的意图与我创建的不同。 - Chris
如果我有一个 Parcelable 包装的对象引用,我能在使用 LocalBroadcastManager 发送的 Intent 中传递它吗? - JohnyTex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接