1. 最近项目中使用到这个进行序列化和反序列化出现报错
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: 。。。
2. 问题所在
查看掘金中这篇文章能解决遇到android.os.BadParcelableException: ClassNotFoundException when unmarshalling解决 - 掘金 (juejin.cn)
如果自己debug进去看 Parcel.java中2789行,readParcelableCreator()方法
HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
loader为null,导致找不到Creator。
public final Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) {
String name = readString();
if (name == null) {
return null;
}
Parcelable.Creator<?> creator;
synchronized (mCreators) {
HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
if (map == null) {
map = new HashMap<>();
mCreators.put(loader, map);
}
creator = map.get(name);
if (creator == null) {}
//。。。。省略
}
}
3. 解决办法
bundle.setClassLoader(getClass().getClassLoader());
在序列化的地方,将ClassLoader设置进去。
4. 原因存疑
上面掘金博主说的原因是下图这个
从我这里的现象却不是这样的,因为没涉及系统内存不足的情况,所以我觉得应该不是这个原因。
5. 查到真正原因ClassLoader不同导致
Bundle中默认的ClassLoader 是继承BaseBundle 中的 BootClassLoader 这个加载器
BaseBundle(@Nullable ClassLoader loader, int capacity) {
mMap = capacity > 0 ?
new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>();
mClassLoader = loader == null ? getClass().getClassLoader() : loader;
}
public ClassLoader getClassLoader() {
if (isPrimitive()) {
return null;
}
return (classLoader == null) ? BootClassLoader.getInstance() : classLoader;
}
public static synchronized BootClassLoader getInstance() {
if (instance == null) {
instance = new BootClassLoader();
}
return instance;
}
这个加载器只加载 系统里面或者SDK的类,当然不会有我们自己写类。
我们打印这个看看getClass().getClassLoader()
看到结果是PathClassLoader,这个ClassLoader是加载APK应用的,所以能找到我们写的类,这很显然~