Подтвердить что ты не робот

"BadParcelableException: ClassNotFoundException при unmarshalling <myclass>" при использовании метода Parcel.read, который имеет ClassLoader как аргумент

Учитывая пользовательский класс org.example.app.MyClass implements Parcelable, я хочу написать List<MyClass> на Посылку. Я сделал сортировку с помощью

 List<MyClass> myclassList = ...
 parcel.writeList(myclassList);

всякий раз, когда я пытаюсь развязать класс с помощью

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

существует исключение "BadParcelableException: ClassNotFoundException when unmarshalling org.example.app.MyClass".

Что здесь не так? Почему класс не найден?

4b9b3361

Ответ 1

Не отключайте пользовательский класс, т.е. предоставляемый вашим приложением, а не платформой Android, с загрузчиком класса framework, который используется, когда вы даете null как аргумент Classloader. Используйте загрузчик классов приложений:

parcel.readList(myclassList, getClass().getClassLoader());

Всякий раз, когда метод Parcel.read*() также имеет аргумент ClassLoader (например, Parcel.readList(List outVal, ClassLoader loader)), и вы хотите прочитать класс приложения из Parcel, используйте загрузчик класса приложения, который можно получить с помощью getClass().getClassLoader().

Фон: Android поставляется с двумя загрузчиками классов: загрузчик системного класса, который может загружать все системные классы, а также те, которые предоставляются вашим приложением. И загрузчик класса приложения, который установил загрузчик системного класса в качестве родительского и, следовательно, может загружать все классы. Если вы дадите null загрузчик классов, Parcel.readParcelableCreator(), будет использовать фреймворк class loader, вызывая в ClassNotFoundException.

Благодаря alexanderblom для предоставления подсказки, которые ведут меня по правильной дорожке

Ответ 2

Я считаю, что более правильной формой этого было бы:

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

Потому что здесь вы явно используете загрузчик классов для универсального типа List.

Ответ 3

Я столкнулся с той же проблемой, и вместо того, чтобы parcleable я использовал bundle

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

intent.putExtra("bundle",bundle);

И в моем классе намерений я использовал это для получения значения:

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

Надеюсь, что это будет полезно для некоторых.