Android &引用;BadParcelableException:解包时ClassNotFoundException<;myclass>&引用;使用Parcel.read方法时,该方法将类加载器作为参数

Android &引用;BadParcelableException:解包时ClassNotFoundException<;myclass>&引用;使用Parcel.read方法时,该方法将类加载器作为参数,android,marshalling,unmarshalling,parcel,Android,Marshalling,Unmarshalling,Parcel,给定一个自定义类org.example.app.MyClass实现了Parcelable,我想将列表写入一个地块。我和他一起做编组 List<MyClass> myclassList = ... parcel.writeList(myclassList); List myclassList=。。。 包裹列表(myclassList); 每当我试图用你的名字来解压这个班级时 List<MyClass> myclassList = new ArrayList<

给定一个自定义类
org.example.app.MyClass实现了Parcelable
,我想将
列表
写入一个地块。我和他一起做编组

 List<MyClass> myclassList = ...
 parcel.writeList(myclassList);
List myclassList=。。。
包裹列表(myclassList);
每当我试图用你的名字来解压这个班级时

 List<MyClass> myclassList = new ArrayList<MyClass>();
 parcel.readList(myclassList, null);
List myclassList=new ArrayList();
parcel.readList(myclassList,空);
在解组org.example.app.MyClass时,存在一个
“BadParcelableException:ClassNotFoundException”
异常


这里怎么了?为什么找不到该类?

当您将
null
作为类加载器参数时,不要使用框架类加载器将自定义类(即,由应用程序提供而不是由Android框架提供的类)解组。使用应用程序类加载器:

parcel.readList(myclassList, getClass().getClassLoader());
无论何时
Parcel.read*()
方法也有一个类加载器作为参数(例如),并且您想要从
Parcel
中读取应用程序类,请使用可以通过
getClass().getClassLoader()
检索的应用程序类加载器

背景:Android附带两个类加载器:系统类加载器,可以加载除应用程序提供的类以外的所有系统类;以及应用程序类加载器,它将系统类加载器设置为其父类,因此能够加载所有类。如果将null作为类装入器,则会导致


感谢alexanderblom为我提供的帮助,使我走上了正确的道路。

我相信更正确的形式是:

List<MyClass> myclassList = new ArrayList<MyClass>();
parcel.readList(myclassList, MyClass.class.getClassLoader());
List myclassList=new ArrayList();
parcel.readList(myclassList,MyClass.class.getClassLoader());

因为这里您显式地将类加载器用于列表的泛型类型。

我遇到了同样的问题,我使用了bundle而不是parcleable

intent.setExtrasClassLoader(getClassLoader());
/* Send optional extras */
Bundle bundle = new Bundle();
bundle.putParcelable("object", mObject);
bundle.putString("stringVal", stringVal);

intent.putExtra("bundle",bundle);
在我的intent类中,我使用它来检索值:

Bundle oldBundle = intent.getBundleExtra("bundle");
ResultReceiver receiver = oldBundle.getParcelable("object");
String stringVal = oldBundle.getString("stringVal");
intent.setExtrasClassLoader(getClassLoader());

希望它对某些人有所帮助。

如果自定义视图子类划分不正确,则可能会出现此错误

假设您正在子类化,并且希望将保存的状态添加到
onSaveInstanceState()
中的超级状态

Parcelable样板文件的不正确实现(从另一个类或模板复制)如下所示:

static class State extends BaseSavedState {

    Bundle stateBundle;

    //incorrect as super state uses ClassLoaderCreator
    public static final Creator<State> CREATOR = new Creator<State>() {
        public State createFromParcel(Parcel in) {
            return new State(in);
        }

        public State[] newArray(int size) {
            return new State[size];
        }
    };

    State(Parcel source) {
        super(source);
        this.stateBundle = source.readBundle(getClass().getClassLoader());
    }

    State(Parcelable superState) {
        super(superState);
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeBundle(stateBundle);
    }
}
请注意,扩展
android.support.v4.view.AbsSavedState
可能比
BaseSavedState
android.view.AbsSavedState
更好,因为它允许您将类加载器传递给超类:

SavedState(Parcel source, ClassLoader classLoader) {
    super(source, classLoader); //available in android.support.v4.view.AbsSavedState
    this.stateBundle = source.readBundle(classLoader);
}

这与我的答案基本相同。
MyClass.class
getClass()
之间没有区别,它们都返回相同的类对象,因为在MyClass中调用了
getClass()
。此外,您可以在这里使用任何类,只要它是一个自定义类,而不是框架提供的类。我没有说您不正确,只是这种形式可能更合适。也可以考虑,当你静态地引用类时,对<代码> GETCARCH()的方法调用是不必要的。在我的例子中,它不起作用。使用类加载器。我在不同的上下文中得到这个错误——在包含可分组的包上调用<代码>捆绑。当针对相关代码运行单个测试类时,它通过了,但运行整个测试套件会导致
BadParcelableException
。“修复”是在
bundle.keySet()
之前执行
bundle.setClassloader(MyClass.class.getClassLoader())
。你好,David Rawson,非常感谢你的回答。这正是我对extended BottomNavigationView的看法。为什么这种情况没有100%发生?我在一些用户设备上得到了这一点,但无法在我的终端上复制。
SavedState(Parcel source, ClassLoader classLoader) {
    super(source, classLoader); //available in android.support.v4.view.AbsSavedState
    this.stateBundle = source.readBundle(classLoader);
}