使用Parcelable是在应用程序之间发送数据的正确方式吗?

7

我正在尝试了解如何在Android应用程序之间进行通信 - 不仅限于Activity实例之间的通信。

我建立了一个'客户端',向服务发送了一个Messenger对象(在发送到服务的Intent中);服务创建了一个消息对象Message并使用messenger.send(message)将其发送回到'客户端'。这很好地运作,直到我尝试使用Message.obj来保存一个对象。

我在服务中创建了自己的ParcelableMyParcelable并将其放入消息中。所有操作都正常进行,直到在'客户端'中取消编组消息。无法反序列化,因为'客户端'无法访问MyParcelable类。这是显而易见的——它们位于不同的包中(例如com.whatever.myclientcom.whatever.myserver)。这样做完全错误吗?

我还尝试创建一个Parcel并发送它(两个应用程序将同时访问该类)——但是Parcel不是Parcelable。我已经阅读了关于使用类加载器的文章,但不理解如何在单独的应用程序(如果我对Android架构的理解正确的话,进程)中使用单独的类加载器。也就是说,如何让一个类加载器“了解”另一个类加载器中存在的类?肯定有一个明显的“这就是你应该做的”方法,但我还没有看到它。

3个回答

3
您无法在不了解该类的进程中对类进行取消编组(正如您已经正确指出的那样)。如果您希望将MyParcelable发送到您的Service,则需要在构建Service时包含MyParcelable,并包括在反序列化时使用的正确ClassLoader,因为反序列化是由系统线程执行的,即使您在编译时包含了MyParcelable,该系统线程也不知道MyParcelable是什么。

编辑:

(a) 将MyParcelable包含在2个不同的包中,并将它们视为相同的类

制作一个公共类的库,并将其包含在两个应用程序(应用程序和Service)中。您可以将其标记为Android库(在Eclipse中,在项目的Android属性下),或者将其导出为JAR并在两个应用程序中导入。将独立的类放入库中总是比直接将它们放入应用程序中要好。这样,您就可以在其他项目中重复使用它们;)

(2) 包括正确的ClassLoader(例如,我从哪里获取正确的类加载器)

当您执行代码时,可以从当前线程获取ClassLoader。显然,这个ClassLoader知道您的类,因为它正在执行您的代码;)例如,在Activity#onCreate()中,您可以执行Thread.currentThread.getContextClassLoader()。由于MyParcelable类也包含在Service中,因此您也可以执行相同的操作以获得有效的ClassLoader

IPC的另一种解决方案是定义一个AIDL接口,因此您不必实现Parcelable


2
嘿m0skit0,你应该再详细解释一下。虽然我也想回答,但你已经说得很对了。再多解释一点会更清晰明了。如果类加载器在序列化和反序列化数据时没有相同的Parcelable类的副本,那么Parcelables只能起到作用。 - G. Blake Meike
听起来不错,但我不知道如何做到以下两点:(a)将MyParcelable包含在2个不同的包中,并使它们被视为同一类;(2)包含正确的ClassLoader(例如,我从哪里获取正确的ClassLoader)。感谢您的回答,但您的理解水平比我的高出大约2个级别。 - Art Swri

1
如果您不想在某个地方使用持久层(我使用云API),您可以在单独的进程中运行服务,并将需要共享值持有者类型对象数据的相应应用程序绑定到该服务上。服务将是您代表连接(绑定)应用程序构建和获取obj值的位置。

这些都是非常好的建议,我一定会在继续学习时密切关注它们。目前,我主要想要掌握Parcelable和类加载器的概念,希望能够理解它们并且能够适当地使用它们。非常感谢您的回答。 - Art Swri
了解Android基础知识和活动生命周期可能比CL概念更重要。http://developer.android.com/reference/android/app/Activity.html http://developer.android.com/guide/components/fundamentals.html - Robert Rowntree
在应用程序之间进行交互,最简单的方法是使用“意图-extra”字段和一个选择器,允许选择目标应用程序。 - Robert Rowntree

1

好的,我找到了我想要的“简单方法”。您可以将Bundle放入Message.obj字段中。 Bundle是可传输的Parcelable,因此可以在客户端和服务器之间传输。由于Bundle已经“内置”在Android Java中,因此不存在服务器不知道其接收的类的问题。而且Bundle显然可以包含其中的“子Bundle”。这比处理确保双方都知道用户定义类的定义要简单。感谢上面的答案-我肯定很欣赏这些信息!


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