"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"
.
Что здесь не так? Почему класс не найден?
Ответы
Ответ 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());
Надеюсь, что это будет полезно для некоторых.