LinkedList, помещенный в Intent extra, перерабатывается в ArrayList при извлечении в следующем действии

Поведение, которое я наблюдаю за передачей сериализуемых данных в качестве дополнительной цели, довольно странно, и я просто хотел уточнить, есть ли что-то, чего я не пропущу.

Итак, я пытаюсь сделать это в том, что в ActivtyA я помещал экземпляр LinkedList в intent я создал для запуска следующего действия – ActivityB .

 LinkedList<Item> items = (some operation); Intent intent = new Intent(this, ActivityB.class); intent.putExtra(AppConstants.KEY_ITEMS, items); 

В onCreate of ActivityB я попытался извлечь дополнительную onCreate LinkedList следующим образом:

 LinkedList<Item> items = (LinkedList<Item>) getIntent() .getSerializableExtra(AppConstants.KEY_ITEMS); 

При выполнении этого я неоднократно получал ClassCastException в ActivityB , в строке выше. В принципе, исключение говорит, что я получаю ArrayList . Как только я изменил код выше, чтобы получить ArrayList , все работает отлично.

Теперь я не могу просто выяснить из существующей документации, является ли это ожидаемым поведением на Android при передаче сериализуемых реализаций List. Или, может быть, есть что-то принципиально неправильное с тем, что я делаю.

Благодарю.

Solutions Collecting From Web of "LinkedList, помещенный в Intent extra, перерабатывается в ArrayList при извлечении в следующем действии"

Я могу сказать вам, почему это происходит, но вам это не понравится 😉

Сначала немного информации о предыстории:

Экстра в Intent в основном представляет собой Android Bundle который в основном представляет собой HashMap пар ключ / значение. Поэтому, когда вы делаете что-то вроде

 intent.putExtra(AppConstants.KEY_ITEMS, items); 

Android создает новый Bundle для дополнительных AppConstants.KEY_ITEMS и добавляет запись карты в Bundle где ключ – AppConstants.KEY_ITEMS а значение – это элементы (который является вашим объектом LinkedList).

Все это хорошо и хорошо, и если вы посмотрите на комплект дополнительных компонентов после выполнения кода, вы обнаружите, что он содержит LinkedList . Теперь идет интересная часть …

Когда вы вызываете startActivity() с содержащим дополнениями, Android необходимо преобразовать дополнительные данные из карты пар ключ / значение в поток байтов. В основном это необходимо для сериализации пакета . Он должен сделать это, потому что он может начать работу в другом процессе, и для этого ему необходимо сериализовать / десериализовать объекты в Bundle, чтобы он мог воссоздать их в новом процессе. Это также необходимо сделать, потому что Android сохраняет содержимое Intent в некоторых системных таблицах, чтобы он мог восстановить Intent, если он понадобится позже.

Чтобы сериализовать Bundle в поток байтов, он проходит через карту в комплекте и получает каждую пару ключ / значение. Затем он принимает каждое «значение» (это какой-то объект) и пытается определить, какой именно объект он может сделать, чтобы он мог сериализовать его наиболее эффективным способом. Для этого он проверяет тип объекта на список известных типов объектов . Список «известных типов объектов» содержит такие вещи, как Integer , Long , String , Map , Bundle и, к сожалению, также List . Поэтому, если объектом является List (из которого существует много разных типов, включая LinkedList ), он сериализует его и помещает в качестве объекта типа List .

Когда Bundle десериализуется, то есть: когда вы это делаете:

 LinkedList<Item> items = (LinkedList<Item>) getIntent().getSerializableExtra(AppConstants.KEY_ITEMS); 

Он создает ArrayList для всех объектов в Bundle типов List .

На самом деле вы ничего не можете сделать, чтобы изменить это поведение Android. По крайней мере теперь вы знаете, почему это так.

Просто чтобы вы знали: я действительно написал небольшую тестовую программу для проверки этого поведения, и я рассмотрел исходный код для Parcel.writeValue(Object v) который является методом, который вызывается из Bundle когда он преобразует карту в байт поток.

Важное примечание. Поскольку List является интерфейсом, это означает, что любой класс, который реализует List который вы помещаете в Bundle , выйдет как ArrayList . Интересно также, что Map также входит в список «известных типов объектов», что означает, что независимо от того, какой тип объекта Map вы кладете в Bundle (например, TreeMap , SortedMap или любой класс, реализующий интерфейс Map ), вы Всегда будет получать HashMap .