Ответ 1
Я могу сказать вам, почему это происходит, но вам это не понравится; -)
Сначала немного справочной информации:
Дополнительно Intent
- это в основном Android Bundle
, который в основном представляет собой HashMap
пары ключ/значение. Поэтому, когда вы делаете что-то вроде
intent.putExtra(AppConstants.KEY_ITEMS, items);
Android создает новый Bundle
для дополнительных функций и добавляет запись карты в Bundle
, где ключ AppConstants.KEY_ITEMS
, а значение элементов (это ваш объект LinkedList).
Все это прекрасно и хорошо, и если вы посмотрите на пакет дополнительных компонентов после выполнения кода, вы обнаружите, что он содержит LinkedList
. Теперь идет интересная часть...
Когда вы вызываете startActivity()
с содержащим дополняющие Intent, Android необходимо преобразовать дополнительные данные из карты пар ключ/значение в поток байтов. В основном это необходимо для сериализации Bundle. Он должен сделать это, потому что он может начать работу в другом процессе, и для этого ему необходимо сериализовать/десериализовать объекты в 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
.