将对象从服务发送到活动(无法编组非 Parcelable)
Posted
技术标签:
【中文标题】将对象从服务发送到活动(无法编组非 Parcelable)【英文标题】:Send Object from Service to Activity (Can't marshal non-Parcelable) 【发布时间】:2011-09-29 14:11:32 【问题描述】:我正在尝试将数据从我的活动发送到服务并接收一些信息,但我得到了:
java.lang.RuntimeException: 不能 编组非 Parcelable 对象 进程。
来自活动的代码如下所示:
Message msg = Message.obtain(null, 1);
msg.obj=1;
msg.replyTo=new Messenger(new PlanRequestIncomingHandler());
try
msgService.send(msg);
catch (RemoteException e)
Log.i(tag, "Can not send msg to service");
e.printStackTrace();
当我设置 msg.obj = something
时,我得到 java.lang.RuntimeException,有人可以帮助我吗?
【问题讨论】:
【参考方案1】:您可以通过 Messenger 传递 Parcelable 类型的对象。或者如果你想通过primitive data types 使用Bundle 包装器,如下所示。
服务结束:
//Create a bundle object and put your data in it
Bundle bundle = new Bundle();
bundle.putInt("key", 1);
Message msg = Message.obtain(null, 123);
msg.obj = bundle;
msg.replyTo = new Messenger(new PlanRequestIncomingHandler());
try
msgService.send(msg);
catch (RemoteException e)
Log.i(tag, "Can't send msg to service");
e.printStackTrace();
活动结束时:
switch(msg.what)
case 123:
if(msg.obj != null)
Bundle bundle = (Bundle) msg.obj;
System.out.println("Got integer "+ bundle.getInt("key"));
break;
干杯:-)
【讨论】:
代码示例不完整!!! switch 写在哪里了?【参考方案2】:老问题,但我正在回答,以便将来可能对某人有所帮助。
如果您使用的是实际对象,那么请务必实现 Parcelable android: How to implement Parcelable to my objects?
但是,正如 OP 所说,他尝试使用 Primitives 但它不起作用,这就是该做的。
问题出在这里msg.obj=1;
这需要一个实现 Parcelable 的实际对象
使用msg.arg1 = 1;
然后您可以使用 msg.arg1
在服务端检索参数
为简单起见,我使用(直接来自我的代码)
Message msg = Message.obtain(null, PlayerService.MSG_ACTION_SEEK, i, -1);
-1 对我来说只是一个持有者。
希望这会有所帮助。
编辑: 小心
Message msg = Message.obtain(null, PlayerService.MSG_ACTION_SEEK, i);
此签名等效于 OP 的第一次尝试,并且需要 Parcelable,这实际上是让我绊倒并让我首先搜索的原因。直到运行时才会抛出错误。
【讨论】:
【参考方案3】:除了原始数据之外,您在活动和服务之间玩转的对象需要实现 Parcelable 并且最好是 Serializable。
希望对你有帮助,
最好的
-serkan
【讨论】:
我有 msg.obj=1 所以它的值是一个原始的并且它不起作用,我尝试了一个实现 Serializable 的自定义对象并且我得到了同样的错误。我认为@CommonsWare 是对的。我会尝试该解决方案并通知您... 当然,请随时通知我们,谢谢乔治,我很感激。【参考方案4】:必须使用Bundle传递常规类型数据,否则会报错:
Java.lang.RuntimeException:不能跨编组进程使用非 Parcelable 对象。
因为Binder交易数据被称为Parcel,所以必须实现Parcelable接口,否则两个应用程序之间无法通信。之所以传递Bundle是因为该类实现了Parcelable接口。当然,如果要传递类还必须实现接口。
你可以这样写:
Message msg = Message.obtain(null, 1);
msg.getData().putInt("key",1);
msg.replyTo=new Messenger(new PlanRequestIncomingHandler());
try
msgService.send(msg);
catch (RemoteException e)
Log.i(tag, "Can not send msg to service");
e.printStackTrace();
对不起,我的英语很糟糕
【讨论】:
【参考方案5】:我已经为 Android 实现了 Actor 模型(如 Akka),因为 Akka 需要 Java 8,所以我为 Android 做了自己的实现,使用 RxJava2,它很容易实现......一旦它在那里,你可以将持有任何对象的消息发送到任何接收者(Activity、Fragment、Service、Pojo 等),而无需担心线程或序列化
如果你不知道什么是Actor Model,我很难详细解释我自己的实现,但是如果你知道,你可以用一种方法制作一个名为“Actor”的接口
void onMessageReceived(Message message);
您可以通过您拥有的任何 Actor 实现此接口,并且要注册任何 Actor,您可以创建一个具有方法的 ActorSystem 类:
static void register(Actor actor, PublishSubject<Message> mailbox);
static void unregister(Actor actor);
static void send(Message message, Class<? extends Actor> ... actors);
当您注册您的 Actor(活动或服务)时,您可以通过以下方式决定接收消息的线程/调度程序:
PublishSubject.observeOn(Schedulers.trampoline());
然后你在 onCreate() 中注册你的 Actor 并在 onDestroy() 中取消注册
或者如果你想要一个库(但我没有测试它),你可以看看这个:
https://github.com/actorapp/droidkit-actors
【讨论】:
以上是关于将对象从服务发送到活动(无法编组非 Parcelable)的主要内容,如果未能解决你的问题,请参考以下文章
GCM 使用 content_available 向 iOS 推送通知(无法从非活动状态调用)