2011-05-05 13 views
51

con respecto a mi ejemplo de código abajo, ¿qué debo hacer si una variable de Locable es nula? En el ejemplo, ahora si l.getZoom() devuelve nulo, obtuve NullPointerException.Cómo serializar el valor nulo al usar la interfaz Parcelable

@Override 
public void writeToParcel(Parcel parcel, int arg1) { 
    parcel.writeInt(count); 
    for(Locable l:locableArr){ 
     parcel.writeInt(l.getOriginId()); 
     parcel.writeInt(l.getLocableType()); 
     parcel.writeInt(l.getZoom()); 
     parcel.writeDouble(l.getLatituda()); 
     parcel.writeDouble(l.getLongituda()); 
     parcel.writeString(l.getTitle()); 
     parcel.writeString(l.getSnipet()); 
    } 

} 

¡Gracias!

+0

Parece que NPE es el resultado del desempaquetado automático. Probablemente debería comprobar el valor nulo y configurarlo en 0? –

+0

Si el zoom tiene valores 0+, considere representar null como -1 – JAL

+0

Por ahora estoy haciendo algo similar, si los valores son NULL estoy escribiendo algunos valores como -1 o cadena vacía que estoy en deserialización en NULL. Feo ... Me gustaría que si alguien puede confirmar que esta es la manera correcta, estaría más satisfecho con mi código. –

Respuesta

13

La mayoría de los códigos de serialización que he visto utilizan indicadores para indicar la presencia/ausencia de un valor O preceden al valor con un campo de conteo (por ejemplo, al escribir matrices) donde el campo de conteo simplemente se pone a cero si el valor no existe en absoluto.

Evaluación del código fuente de las clases básicas Android revela código como este (de la clase de mensaje):

if (obj != null) { 
     try { 
      Parcelable p = (Parcelable)obj; 
      dest.writeInt(1); 
      dest.writeParcelable(p, flags); 
     } catch (ClassCastException e) { 
      throw new RuntimeException(
       "Can't marshal non-Parcelable objects across processes."); 
     } 
    } else { 
     dest.writeInt(0); 
    } 

o esto (de la clase Intención):

if (mCategories != null) { 
     out.writeInt(mCategories.size()); 
     for (String category : mCategories) { 
      out.writeString(category); 
     } 
    } else { 
     out.writeInt(0); 
    } 

Mi sugerencia: En su código, si no hay diferencia funcional entre "zoom == null" y "zoom == 0", entonces simplemente declararía el zoom como primitivo (int en lugar de Integer) O lo inicializaría a cero en el constructo y asegúrese de nunca configurarlo como nulo (entonces se le puede garantizar que nunca será nulo y no tendrá que agregar un código especial para tratarlo en sus métodos de serialización/deserialización).

91

Puede usar Parcel.writeValue para ordenar objetos genéricos con valor nulo.

+42

y para volver a leer el valor ... s = (String) in.readValue (String.class.getClassLoader()); –

+0

¡Genial! Gracias. – tasomaniac

+2

@SofiSoftwareLLC mirando el código fuente de parcel.readValue solo necesita un cargador de clases para los tipos Map, Parcelable, ArrayList, Object [] y Parcelable []. Para otros tipos, puede pasar nulo para el cargador de clases. https: // github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java/android/os/Parcel.java # L2002 – miguel

10

Esta es la solución que se me ocurrió grabar series de seguridad:

private void writeStringToParcel(Parcel p, String s) { 
    p.writeByte((byte)(s != null ? 1 : 0)); 
    p.writeString(s); 
} 

private String readStringFromParcel(Parcel p) { 
    boolean isPresent = p.readByte() == 1; 
    return isPresent ? p.readString() : null; 
} 
+0

Tuve algunos problemas con esto después de haber copiado y pegado el código, sin darme cuenta de que en readStringFromParcel() tuve que lanzar el 1 a byte antes de compararlo con p.readByte(). Al final, elegí "p.writeInt ((s! = Null? 1: 0));" y "boolean isPresent = p.readInt() == 1;" – Matt

+3

Debe escribir la cadena utilizando la línea 'p.writeString (s)' solo cuando no sea nulo; de lo contrario, obtendrás una NullPointerException en esta línea. – Price

+0

Si está utilizando 'p.writeParcelable' en lugar de' p.writeString', no obtendrá una NullPointerException inmediatamente, sino más tarde alguna clase de ClassCastException con sombra causada por las secuencias de lectura y escritura desalineadas. Solo debe escribir el objeto si no es nulo. – Roland

11

estoy usando una clase Parcelable que tiene Integer y Boolean campos también, y esos campos puede ser nulo.

Tuve problemas para usar el método genérico Parcel.writeValue, particularmente cuando estaba tratando de leerlo de nuevo a través de Parcel.readValue. Seguí recibiendo una excepción de tiempo de ejecución que decía que no podía determinar el tipo de objeto parcelado.

En última instancia, yo era capaz de resolver el problema mediante el uso Parcel.writeSerializable y Parcel.readSerializable con un molde tipo, ya que ambos Integer y Boolean implementar la interfaz Serializable. Los métodos de lectura y escritura manejan los valores null por usted.

+0

Esto realmente funciona. –

Cuestiones relacionadas