How to use writeStringArray() and readStringArray() in a Parcel

Rafael T picture Rafael T · Jan 17, 2013 · Viewed 9.6k times · Source

I recently came across a very stupid (at least from my point of view) implementation inside Androids Parcel class.

Suppose I have a simple class like this

class Foo implements Parcelable{

    private String[] bars;
    //other members

    public in describeContents(){ 
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags){

        dest.writeStringArray(bars);
        //parcel others
    }

    private Foo(Parcel source){
        source.readStringArray(bars);
        //unparcel other members
    }

    public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>(){

         public Foo createFromParcel(Parcel source){
             return new Foo(source);
         }

         public Foo[] newArray(int size){
             return new Foo[size];
         }

    };
}

Now, if I want to Parcel a Foo Object and bars is null I see no way to recover from this situation (exept of catching Exceptions of course). Here is the implementation of these two methods from Parcel:

 public final void writeStringArray(String[] val) {
        if (val != null) {
            int N = val.length;
            writeInt(N);
            for (int i=0; i<N; i++) {
                writeString(val[i]);
            }
        } else {
            writeInt(-1);
        }
    }


  public final void readStringArray(String[] val) {
        int N = readInt();
        if (N == val.length) {
            for (int i=0; i<N; i++) {
                val[i] = readString();
            }
        } else {
            throw new RuntimeException("bad array lengths");
        }
    }

So writeStringArray is fine if I pass bars which are null. It just writes -1 to the Parcel. But How is the method readStringArray supposed to get used? If I pass bars inside (which of course is null) I will get a NullPointerException from val.length. If I create bars before like say bars = new String[???] I don't get any clue how big it should be. If the size doesn't match what was written inside I recieve a RuntimeException.

Why is readStringArray not aware of a result of -1 which gets written on null objects from writeStringArray and just returns?

The only way I see is to save the size of bars before I call writeStringArray(String[]) which makes this method kind of useless. It will also redundatly save the size of the Array twice (one time for me to remember, the second time from writeStringArray).

Does anyone know how these two methods are supposed to be used, as there is NO java-doc for them on top?

Answer

Vladimir Mironov picture Vladimir Mironov · Jan 17, 2013

You should use Parcel.createStringArray() in your case.

I can't imagine a proper use-case for Parcel.readStringArray(String[] val) but in order to use it you have to know the exact size of array and manually allocate it.