How to serialize null value when using Parcelable interface
Solution 1
You can use Parcel.writeValue
for marshalling generic object with null value.
Solution 2
I'm using a Parcelable
class that has Integer
and Boolean
fields as well, and those fields can be null.
I had trouble using the generic Parcel.writeValue
method, particularly when I was trying to read it back out via Parcel.readValue
. I kept getting a runtime exception that said it couldn't figure out the type of the parceled object.
Ultimately, I was able to solve the problem by using Parcel.writeSerializable
and Parcel.readSerializable
with a type cast, as both Integer
and Boolean
implement the Serializable interface. The read and write methods handle null
values for you.
Solution 3
This is the solution I came up with to write strings safely:
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;
}
Solution 4
Most serialization code that I've seen uses either flags to indicate the presence/absence of a value OR precedes the value with a count field (for example, when writing arrays) where the count field is just set to zero if the value doesn't exist at all.
Examining the source code of Android core classes reveals code like this (from Message class):
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);
}
or this (from Intent class):
if (mCategories != null) {
out.writeInt(mCategories.size());
for (String category : mCategories) {
out.writeString(category);
}
} else {
out.writeInt(0);
}
My suggestion: In your code, if there is no functional difference between "zoom == null" and "zoom == 0", then I would just declare zoom as a primitive (int
instead of Integer
) OR initialize it to zero in the constructor and ensure that you never set it to null (then you can be guaranteed that it will never be null and you won't have to add special code to deal with that in your serialization/deserialization methods).
igor.beslic
Updated on July 08, 2022Comments
-
igor.beslic almost 2 years
regarding my code example down, what shold I do if one Locable's variables is null? In example, now if l.getZoom() returns null, I got NullPointerException.
@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()); } }
Thanks!
-
Sofi Software LLC over 11 yearsand to read the value back... s = (String) in.readValue(String.class.getClassLoader());
-
Matt about 11 yearsI had some trouble with this after i copied and pasted your code, not realizing that in readStringFromParcel() i had to cast the 1 to byte before comparing it to p.readByte(). In the end I chose to "p.writeInt((s != null ? 1 : 0));" and "boolean isPresent = p.readInt() == 1;"
-
Price almost 10 yearsYou should write the string using the line
p.writeString(s)
only when it is not null; otherwise you will get a NullPointerException at this line. -
miguel about 9 years@SofiSoftwareLLC looking at the source code of parcel.readValue it only needs a class loader for types Map, Parcelable, ArrayList, Object[] and Parcelable[]. For other types you can pass in null for the classloader. github.com/android/platform_frameworks_base/blob/…
-
Admin about 6 yearsIf you are using
p.writeParcelable
instead ofp.writeString
you won't get a NullPointerException immediately, just some shady ClassCastException later on caused by the misaligned read and write sequences. You should only write the object if it is not null. -
meszias over 5 yearsYou could write the code for answering the part of reading the object.
-
arenaq about 5 yearsYep, serializable with cast is working like a charm.
-
ArteFact about 5 yearsShould be accepted answer, with @SofiSoftwareLLC 's comment integration