6

Is it possible to write null to Parcel when parcelling an object, and get null back again when unparcelling it again?

Let's assume we have the following code:

public class Test implements Parcelable {
    private String string = null;
    public Test(Parcel dest, int flags) {
        source.writeString(string);
    }
}

Will I get a NullPointerException when reading this value back from the parcel using Parcel.readString()?

Or will I get a null value out?

Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
Fattum
  • 996
  • 1
  • 9
  • 23

3 Answers3

17

Yes, you can pass a null to the Parcel.writeString(String) method.

When you read it out again with Parcel.readString(), you will get a null value out.


For example, assume you have a class with the following fields in it:

public class Test implements Parcelable {
    public final int id;
    private final String name;
    public final String description;
    ...

You create the Parcelable implementation like this (using Android Studio autoparcelable tool):

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(id);
    dest.writeString(null); // NOTE the null value here
    dest.writeString(description);
}

protected Test(Parcel in) {
    id = in.readInt();
    name = in.readString();
    description = in.readString();
}

When running this code, and passing a Test object as a Parcelable extra in an Intent, 2 points become apparent:

  1. the code runs perfectly without any NullPointerException
  2. the deserialised Test object has a value name == null

You can see similar info in the comments to this related question:

Community
  • 1
  • 1
Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
  • 1
    This is exactly the behaviour I expected! Thank you for the corrections. – Fattum Dec 19 '15 at 15:10
  • I'm having apparent problems serializing Double values (that can be null) - when reading from the Parcel with readDouble() i get a double (primitive) back, and that fails, with "Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference" – tplive Jul 06 '18 at 07:35
  • Yes, `getDouble()` returns a primitive double that would have to have been added with `setDouble()` which also takes a primitive double. I imagine if you try that with a null `Double` object you would run into problems. – Richard Le Mesurier Jul 06 '18 at 09:17
  • I have a List of custom class right after a string that can be null. If I call writeString() as normal as you show above, I get the nasty unmarshalling unknown type error for the next List during deserialization of Parcelable. If I use empty string if it is null, then it works perfectly. – Mehmed Oct 22 '18 at 10:03
  • @Mehmed you should probably post that as a new question with full details. I recommend linking to this question and answer, explaining the differences in detail so it does not get closed as a duplicate (which would be likely otherwise). – Richard Le Mesurier Oct 22 '18 at 12:05
1

If you want to write other data types such as Integer, Double, Boolean with possible null values to a parcel, you can use Parcel.writeSerializable().

When reading these values back from parcel, you have to cast the value returned by Parcel.readSerializable() to the correct data type.

Double myDouble = null;
dest.writeSerializable(myDouble);  // Write

Double readValue = (Double) dest.readSerializable();   // Read
Lahiru Chandima
  • 22,324
  • 22
  • 103
  • 179
0

In my case (Kotlin)

 override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(if (PapperId == null) -1 else PapperId)
        parcel.writeString( if (Nome == null) "" else Nome)
}
FlipNovid
  • 1,191
  • 3
  • 12
  • 20
  • Imo using default values must be used only after a case analysis. If we'd use your method to store a Integer price, then without value it would default to 0, i can buy it, a lot of it !! Really, no value is different than default value. – Mostrapotski Jul 05 '19 at 07:08