tôi có thể cho bạn biết lý do tại sao điều này xảy ra, nhưng bạn sẽ không thích nó ;-)
Lần đầu tiên một chút thông tin cơ bản:
Extras trong một Intent
về cơ bản Android Bundle
về cơ bản là các cặp khóa/giá trị HashMap
. Vì vậy, khi bạn làm điều gì đó như
intent.putExtra(AppConstants.KEY_ITEMS, items);
Android tạo ra một Bundle
mới cho tính năng bổ sung và thêm một mục bản đồ để các Bundle
nơi quan trọng là AppConstants.KEY_ITEMS
và giá trị là mục (đó là đối tượng LinkedList của bạn).
Điều này là tốt và tốt, và nếu bạn xem xét gói tính năng bổ sung sau khi mã của bạn thực hiện, bạn sẽ thấy rằng nó có chứa LinkedList
. Bây giờ đến phần thú vị ...
Khi bạn gọi startActivity()
với Intent có tính năng bổ sung, Android cần phải chuyển đổi phần bổ sung từ bản đồ các cặp khóa/giá trị thành luồng byte. Về cơ bản nó cần phải serialize Bundle. Nó cần phải làm điều đó bởi vì nó có thể bắt đầu hoạt động trong một quá trình khác và để làm điều đó nó cần serialize/deserialize các đối tượng trong Bundle để nó có thể tái tạo chúng trong quá trình mới. Nó cũng cần phải làm điều này bởi vì Android lưu nội dung của Intent trong một số bảng hệ thống để nó có thể tạo lại Intent nếu nó cần sau này.
Để tuần tự hóa Bundle
thành luồng byte, nó đi qua bản đồ trong gói và nhận mỗi cặp khóa/giá trị. Sau đó, nó mất mỗi "giá trị" (đó là một số loại đối tượng) và cố gắng để xác định loại đối tượng nó là gì để nó có thể serialize nó một cách hiệu quả nhất. Để thực hiện điều này, nó sẽ kiểm tra kiểu đối tượng dựa vào danh sách các loại đối tượng đã biết.Danh sách "loại đối tượng đã biết" chứa những thứ như Integer
, Long
, String
, Map
, Bundle
và không may là List
. Vì vậy, nếu đối tượng là List
(trong đó có nhiều loại khác nhau, bao gồm LinkedList
), nó sẽ nối tiếp nó và đánh dấu nó là đối tượng thuộc loại List
.
Khi Bundle
được deserialized, ví dụ: khi bạn làm điều này:
LinkedList<Item> items = (LinkedList<Item>)
getIntent().getSerializableExtra(AppConstants.KEY_ITEMS);
nó tạo ra một ArrayList
cho tất cả các đối tượng trong Bundle
loại List
.
Không thực sự bất cứ điều gì bạn có thể làm để thay đổi hành vi này của Android. Ít nhất bây giờ bạn biết tại sao nó làm điều này.
Chỉ để bạn biết: Tôi thực sự đã viết một chương trình thử nghiệm nhỏ để xác minh hành vi này và tôi đã xem mã nguồn cho Parcel.writeValue(Object v)
là phương thức được gọi từ Bundle
khi chuyển đổi bản đồ thành luồng byte.
Lưu ý quan trọng: Kể từ List
là một giao diện điều này có nghĩa rằng bất kỳ lớp mà thực hiện List
mà bạn đưa vào một Bundle
sẽ đi ra như một ArrayList
. Nó cũng thú vị là Map
cũng nằm trong danh sách "các loại đối tượng nổi tiếng" có nghĩa là không có vấn đề gì loại Map
đối tượng bạn đưa vào một Bundle
(ví dụ TreeMap
, SortedMap
, hoặc bất kỳ lớp mà thực hiện giao diện Map
), bạn sẽ luôn nhận được HashMap
trong số đó.
sử dụng Ghim thay thế. –
nhưng có lý do cụ thể nào khiến 'LinkedList' xảy ra, trong khi, nếu tôi đã thêm một cá thể' ArrayList' làm dữ liệu phụ trên 'intent' thì mọi thứ sẽ ổn. Và, tôi sẽ không cần phải sử dụng 'Parcelable'? – anirvan
+1 cho câu hỏi thú vị. Tôi đã dành một chút thời gian suy nghĩ về điều này và rất hấp dẫn, tôi đã tìm ra nó cho bản thân mình. Bây giờ bạn và tôi đều thông minh hơn (xem câu trả lời của tôi). –