将 Serilizable 转换为 HashMap 的派生
Casting Serilizable to derivation of HashMap
我正在尝试使用 .putExtra() 和 sendBroadcast() 将一些工作从 IntentService 发送到 BroadcastReceiver,所以我有自己的 class 调用 "Message",它扩展了 HashMap< String,String > 并实现可序列化。
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());
}
}
这是 Android SDK 中的一个错误(尚未修复)。在 bug report 中它是一个 ArrayList
,但它也适用于实现 Map
或 List
的 类。
在错误报告中,有人建议使用以下 holder 作为修复:
public class SerializableHolder implements Serializable {
private Serializable content;
public Serializable get() {
return content;
}
public SerializableHolder(Serializable content) {
this.content = content;
}
}
但我的建议是改为实施 Parcelable
,它是为 android 设计的,比 Serializable
.
快得多
你不会喜欢这个答案。
额外内容存储在 Bundle
中。 Android 对 Bundle
的内容做一些 "optimizations" 并且它试图在知道条目类型的情况下如何 serialize/deserialize 变得聪明。因此,如果您将实现 Map
接口的任何东西放入 Bundle
,当您将其取回时,您将得到一个 HashMap
:-(
有关机制的详细说明,请参阅 my answer to this question。
要解决您的问题,您需要让您的自定义 class 使用 (即:包含)HashMap
而不是 be(即:继承自)a HashMap
.
我正在尝试使用 .putExtra() 和 sendBroadcast() 将一些工作从 IntentService 发送到 BroadcastReceiver,所以我有自己的 class 调用 "Message",它扩展了 HashMap< String,String > 并实现可序列化。
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());
}
}
这是 Android SDK 中的一个错误(尚未修复)。在 bug report 中它是一个 ArrayList
,但它也适用于实现 Map
或 List
的 类。
在错误报告中,有人建议使用以下 holder 作为修复:
public class SerializableHolder implements Serializable {
private Serializable content;
public Serializable get() {
return content;
}
public SerializableHolder(Serializable content) {
this.content = content;
}
}
但我的建议是改为实施 Parcelable
,它是为 android 设计的,比 Serializable
.
你不会喜欢这个答案。
额外内容存储在 Bundle
中。 Android 对 Bundle
的内容做一些 "optimizations" 并且它试图在知道条目类型的情况下如何 serialize/deserialize 变得聪明。因此,如果您将实现 Map
接口的任何东西放入 Bundle
,当您将其取回时,您将得到一个 HashMap
:-(
有关机制的详细说明,请参阅 my answer to this question。
要解决您的问题,您需要让您的自定义 class 使用 (即:包含)HashMap
而不是 be(即:继承自)a HashMap
.