2012-01-05 39 views
23
// Application ... 
Intent i = new Intent(); 
i.putExtra(EXTRA_FILE_UPLOAD_URIS, mGalleryAdapter.getItems()); 

Uri[] getItems() { return mItems; } 

// Service ... 
intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); //works, returns Parcelable[] 
Uri[] uris = (Uri[])intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); 
// ... Breaks with ClassCastException 

Tại sao các diễn viên để Uri[] giờ nghỉ, khi UriParcelable?Tôi không hiểu lý do tại sao điều này xảy ra ClassCastException

+0

Đăng stacktrace. –

+0

'Uri' có kế thừa từ' Parcelable' hoặc ngược lại không? – fge

+0

Uri thực hiện Parcelable –

Trả lời

19

Rất tiếc, không có cách nào để truyền như vậy cho các mảng trong Java. Bạn sẽ phải lặp mảng của bạn và tạo từng đối tượng riêng lẻ.

Lý do cho điều này là loại An toàn, JVM không thể đảm bảo rằng nội dung của mảng của bạn có thể được đúc thành Uri, mà không phải lặp lại thông qua chúng, đó là lý do tại sao bạn phải lặp lại chúng và truyền riêng chúng.

Về cơ bản vì có thể được kế thừa bởi các đối tượng khác, không có gì đảm bảo rằng Mảng chỉ chứa các đối tượng Uri. Tuy nhiên việc đúc thành một siêu kiểu sẽ làm việc kể từ đó loại an toàn sẽ ổn.

+0

Tôi nghĩ như vậy (vì nó là như vậy trong C#) vì vậy tôi nhìn lên hiệp phương sai mảng java và nó có vẻ được hỗ trợ (và là một lỗ trong an toàn loại). Tài liệu tham khảo của tôi chỉ đơn giản là lỗi thời với JVM hiện tại? : http://www.angelikalanger.com/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm, http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety –

+1

Tôi nghĩ rằng loại an toàn có liên quan đến generics, được giới hạn trong compiletime . Mảng không được mở rộng. Chúng là tài liệu tham khảo và bạn có thể thực hiện truyền. –

+0

phải, nhưng Bưu kiện [] là một Uri mới [] ở vị trí đầu tiên ... vì vậy nó phải được mặc dù Uri là một bưu kiện nhưng Uri [] không phải là một Parcelable [] ... –

0

Tôi nghĩ rằng những gì đang xảy ra là một cái gì đó như sau:

class Parent { } 

class MaleParent extends Parent { } 

class FemaleParent extends Parent { } 

Nếu kịch bản là một cái gì đó như trên thì sau đây sẽ thất bại trong thời gian chạy:

Parent[] parents = new FemaleParent[]{}; 
MaleParent[] maleParents = (MaleParent[]) parents; 

Something như sau không làm tăng ngoại lệ :

Parent[] parents = new MaleParent[]{}; 
MaleParent[] maleParents = (MaleParent[]) parents; 
+0

tại sao rất nhiều cha mẹ? – Sayka

26

Sử dụng phương pháp này, nó phù hợp với tôi.

Parcelable[] ps = getIntent().getParcelableArrayExtra(); 
Uri[] uri = new Uri[ps.length]; 
System.arraycopy(ps, 0, uri, 0, ps.length); 
9

Mảng có hành vi đa hình - chỉ loại chung không có.

Nghĩa là, nếu Uri thực hiện Parcelable sau đó

Bạn có thể nói:

Parcelable[] pa = new Uri[size]; 
Uri[] ua = (Uri[]) pa; 

bạn KHÔNG THỂ nói:

List<Parcelable> pl = new ArrayList<Uri>(); 

Như bạn thấy chúng ta có thể đúc pa trở lại Uri[]. Vậy vấn đề là gì? Điều này ClassCastException xảy ra khi ứng dụng của bạn bị giết và sau đó mảng đã lưu được tạo lại. Khi nó được tái tạo thời gian chạy không biết loại mảng (Uri[]) nó đã được như vậy nó chỉ tạo ra một Parcelable[] và đặt các yếu tố vào nó. Do đó, ClassCastException khi bạn cố gắng truyền tới Uri[].

Lưu ý rằng ngoại lệ không xảy ra (theo lý thuyết) khi quá trình không bị giết và mảng được tạo ban đầu (Uri[]) được sử dụng lại giữa các vòng lưu/khôi phục trạng thái. Giống như khi bạn thay đổi hướng.

Tôi chỉ muốn nêu rõ TẠI SAO nó xảy ra. Nếu bạn muốn một giải pháp @solo cung cấp một phong nha.

Chúc mừng

+1

Đây là câu trả lời đúng. Tôi tình cờ xuất hiện khi xuất hiện lại ClassCastException một cách không thường xuyên khi Dịch vụ của tôi đã cố gắng truyền Parcelable [] từ Bundle của AccountManager sang Tài khoản []. Nó đã xảy ra rất hiếm khi sau các cuộc gọi điện thoại, và cuối cùng - đây là thủ phạm! – user1643723

Các vấn đề liên quan