How to serialize null value when using Parcelable interface

AndroidNullpointerexceptionParcelable

Android Problem Overview


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!

Android Solutions


Solution 1 - Android

You can use Parcel.writeValue for marshalling generic object with null value.

Solution 2 - Android

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 - Android

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 - Android

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).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionigor.beslicView Question on Stackoverflow
Solution 1 - AndroidartchView Answer on Stackoverflow
Solution 2 - AndroidJustin HongView Answer on Stackoverflow
Solution 3 - AndroidFelipe LimaView Answer on Stackoverflow
Solution 4 - AndroidDavid WasserView Answer on Stackoverflow