【问题标题】:Casting Serilizable to derivation of HashMap将 Serilizable 转换为 HashMap 的派生
【发布时间】:2015-06-17 18:00:44
【问题描述】:

我正在尝试使用 .putExtra() 和 sendBroadcast() 将一些工作从 IntentService 发送到 BroadcastReceiver,所以我有自己的名为“Message”的类,它扩展了 HashMap 并实现了 Serializable。

public class Message extends HashMap<String,String> implements Serializable{
    public MessageID ID;
    public int Encode(byte[] buff,int off);
    public int Decode(byte[] buff,int off);
    //...
}

我是这样发送的:

public static void ProcessMessage(Message msg) {
    Intent broadcastIntent = new Intent();
    broadcastIntent.setAction(Receiver.BROADCAST);
    broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
    broadcastIntent.putExtra("MESSAGE",(Serializable)msg);
    parentService.sendBroadcast(broadcastIntent);
    Print("Broadcasting intent to receiver ("+Receiver.BROADCAST+") from: "+parentService.toString());
}

并像这样接收:

public void onReceive(Context context, Intent intent) {
    Sys.Print("Receiver handling: "+intent.getAction());
    if(intent.getAction().equals(BROADCAST)){
        try {
            Message msg = (Message) intent.getSerializableExtra("MESSAGE");
            Sys.Print("Receiver handling " + msg.ID.toString());
        } catch(Exception ex){
            Sys.Print("Failed handling message, reason: "+ex.getStackTrace().toString());
        }
    }
}

但在这里我总是得到这个:"Failed handling message, reason: java.lang.ClassCastException: java.util.HashMap"

知道可能出了什么问题吗?

堆栈跟踪:

com.myapp.Receiver.onReceive(Receiver.java:24)
android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:709)
android.os.Handler.handleCallback(Handler.java:587)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:138)
android.app.ActivityThread.main(ActivityThread.java:3701)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:507)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
dalvik.system.NativeStart.main(Native Method)

所以最后,如果有人有类似的问题,我是这样解决的:

public class Message implements Parcelable {
    public HashMap<String,String> Data;
    public Message(){
        Data=new HashMap<>();
    }
    public int Encode(byte[] buff,int off);
    public int Decode(byte[] buff,int off);
    public void Add(String i,String v);
    public String At(String i);
    public boolean ContainsKey(String i);
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeMap(this.Data);
    }
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Message createFromParcel(Parcel in) {
            return new Message(in);
        }
        public Message[] newArray(int size) {
            return new Message[size];
        }
    };
    public Message(Parcel in) {
        Data=new HashMap<>();
        in.readMap(this.Data,String.class.getClassLoader());
    }
}

【问题讨论】:

  • 请放置整个堆栈跟踪。你在两边都使用同一个 JVM 吗?
  • 我直接在设备上运行它。

标签: java android android-intent serializable receiver


【解决方案1】:

你不会喜欢这个答案。

额外内容存储在Bundle 中。 Android 对Bundles 的内容进行了一些“优化”,如果知道条目的类型,它会尝试对如何序列化/反序列化条目进行智能处理。因此,如果您将实现Map 接口的任何东西放入Bundle,当您将其取出时,您将获得HashMap :-(

有关机制的详细说明,请参阅my answer to this question

要解决您的问题,您需要让您的自定义类使用(即:包含)HashMap 而不是成为(即:继承自) HashMap

【讨论】:

    【解决方案2】:

    这是 Android SDK 中的一个错误(尚未修复)。在bug report 中它是一个ArrayList,但它也适用于实现MapList 的类。

    在错误报告中,有人建议使用以下支架作为修复:

    public class SerializableHolder implements Serializable {
        private Serializable content;
        public Serializable get() {
            return content;
        }
        public SerializableHolder(Serializable content) {
            this.content = content;
        }
    }
    

    但我的建议是改用 Parcelable,它是为 android 设计的,比 Serializable 快很多。

    【讨论】:

    • 现在我总是遇到,getParcelableExtra("MESSAGE") 总是返回 null,我这样做 broadcastIntent.putExtra("MESSAGE", (Parcelable) msg);
    • “错误”与实现Serializable 无关。该错误与实现MapList 接口的类的Android 优化有关。见my answer to this question.
    • @DavidWasser 所以你是说实现Parcelable 而不是Serializable 不会解决这个问题?
    • @jakubinf 你是否为Parcelable 实现了必要的方法?见stackoverflow.com/a/7181792/1690982
    • 不。即使该类实现了Parcelable 而不是Serializable,任何从Bundle 中获取此类实例的尝试都将导致HashMap
    猜你喜欢
    • 1970-01-01
    • 2017-01-08
    • 2013-11-17
    • 2016-12-12
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多