Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 283
Rafael T Avatar asked Jan 17 '13 18:01

Rafael T


People also ask

What are Android parcels?

A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.

What is the difference between Serializable and Parcelable?

Serializable is a standard Java interface. You simply mark a class Serializable by implementing the interface, and Java will automatically serialize it in certain situations. Parcelable is an Android specific interface where you implement the serialization yourself.

What is Parcelable Android example?

Parcelable is a serialization mechanism provided by Android to pass complex data from one activity to another activity.In order to write an object to a Parcel, that object should implement the interface “Parcelable“.

What is parcel in Kotlin?

Save. In Android, to pass the data from one activity to another activity, we use the Parcelable. The kotlin-parcelize plugin provides a Parcelable implementation generator. The Android's Parcelable is an interface on which, the values can be written and read from a Parcel.


2 Answers

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.

like image 162
Vladimir Mironov Avatar answered Oct 26 '22 02:10

Vladimir Mironov


It's not really clear from the (lack of) documentation but readStringArray() is to be used when the object already knows how to create the string array before calling this function; for example when it's statistically instanciated or it's size is known from another previously read value.

What you need here is to call the function createStringArray() instead.

like image 33
SylvainL Avatar answered Oct 26 '22 01:10

SylvainL