2012-01-05 18 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 

¿Por qué el elenco de Uri[] descanso, cuando Uri es Parcelable?que no entiendo por qué se produce este ClassCastException

+0

Publique la stacktrace. –

+0

¿'Uri' hereda de' Parcelable' o al revés? – fge

+0

Implementa Uri Parcelable –

Respuesta

19

Desafortunadamente no hay forma de lanzar de esa manera para las matrices en Java. Tendrá que iterar su matriz y lanzar cada objeto individualmente.

El motivo de esto es el tipo Seguridad, el JVM simplemente no puede garantizar que el contenido de su matriz se pueda convertir a Uri, sin tener que iterar a través de ellos, razón por la cual debe iterarlos y convertirlos individualmente.

Básicamente porque Parcelable podría ser heredado por otros objetos, no hay garantía de que la matriz contenga solo objetos Uri. Sin embargo, la conversión a un supertipo funcionaría, ya que la seguridad del tipo estaría bien.

+0

Pensé lo mismo (ya que es así en C#), así que busqué la covarianza de array java y parece ser compatible (y para ser un agujero en la seguridad del tipo). ¿Mis referencias simplemente están desactualizadas con la JVM actual? : http://www.angelikalanger.com/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm, http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety –

+1

Creo que la seguridad del tipo está relacionada con los genéricos, que se limita al tiempo de compilación. . Las matrices no están genéricas. Son referencias y puedes hacer casting. –

+0

a la derecha, pero Parcelable [] era un nuevo Uri [] en primer lugar ... por lo que debe ser aunque Uri sea Parcelable pero Uri [] no es Parcelable [] ... –

0

Creo que lo que está sucediendo es algo de la siguiente manera:

class Parent { } 

class MaleParent extends Parent { } 

class FemaleParent extends Parent { } 

Si el escenario es algo que el anterior, entonces el siguiente fallará en tiempo de ejecución:

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

Algo de la siguiente manera no plantea la excepción :

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

¿por qué tantos padres? – Sayka

26

Utilice este método, me funciona.

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

matrices tienen comportamiento polimórfico - únicos tipos genéricos no tienen.

Es decir, si Uri implementa Parcelable continuación

se puede decir:

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

no se puede decir:

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

Como se ve podemos echar pa de nuevo a Uri[]. ¿Entonces cuál es el problema? Este ClassCastException se produce cuando se elimina la aplicación y luego se vuelve a crear la matriz guardada. Cuando se recrea, el tiempo de ejecución no sabe qué tipo de matriz (Uri[]) era, por lo que solo crea un Parcelable[] y coloca elementos en él. De ahí el ClassCastException cuando intentas convertirlo al Uri[].

Tenga en cuenta que la excepción no ocurre (teóricamente) cuando el proceso no se cancela y la matriz creada originalmente (Uri[]) se reutiliza entre las salvaciones/restauraciones del estado. Como cuando cambias la orientación.

Solo quería aclarar POR QUÉ sucedió. Si quieres una solución @solo proporciona una solución decente.

Cheers

+1

Esta es LA respuesta correcta. Me tropecé con la aparición de ClassCastException esporádicamente cuando mi Servicio intentó lanzar Parcelable [] desde el Paquete de AccountManager a la Cuenta []. Sucedió muy raramente después de las llamadas telefónicas, y finalmente, ¡aquí está el culpable! – user1643723

Cuestiones relacionadas