41

I'd like to make class A Parcelable.

public class A {
    public String str;
    public ArrayList<B> list;
}

This is what I've come up with so far. However it crashes with a NullPointerException. The problem are these two statements: dest.writeList(list); & in.readList(list, this.getClass().getClassLoader());. I can't figure out what to do from here :(

Class A

public class A implements Parcelable {
    public String str;
    public ArrayList<B> list;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
        dest.writeList(list);
    }

    private A(Parcel in) {
        str = in.readString();
        in.readList(list, this.getClass().getClassLoader());
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

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

Class B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

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

Thank you for your time.

Snæbjørn
  • 10,322
  • 14
  • 65
  • 124

7 Answers7

56

I finally figured out what to type into Google :), and found this Android, How to use readTypedList method correctly in a Parcelable class?

The solution was to use read-/writeTypedList instead. I also initialize the arraylist to avoid any further NullPointerException.

Class A

public class A implements Parcelable {
    public String str;
    public ArrayList<B> list = new ArrayList<B>();

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
        dest.writeTypedList(list);
    }

    private A(Parcel in) {
        str = in.readString();
        in.readTypedList(list, B.CREATOR);
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

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

Class B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

        public B[] newArray(int size) {
            return new B[size];
        }
    };
}
Community
  • 1
  • 1
Snæbjørn
  • 10,322
  • 14
  • 65
  • 124
  • Ah yes, it wouldn't let me and then I sort of forgot about it :) – Snæbjørn Jan 09 '13 at 16:21
  • @Snæbjørn +1 for showing how to make a parcelable class that contain non-primitive or custom types. – ripopenid Dec 07 '13 at 05:10
  • Awesome example. May I suggest you fix the names of the "AcreateFromParcel" functions in both classes? In the A class should be "public A createFromParcel" (missing space) and in the B class should be "public B createFromParcel". Yeah, it's trivial but for newbies can be troublesome. – Miguel El Merendero Feb 18 '14 at 08:42
32

If you have only one Parcelable object inside your main Parcelable object, not list like the accepted answer case. Then it will be like the following:

Class A

public class A implements Parcelable {
    public String str;
    public B objectB;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        //The parcelable object has to be the first one
        dest.writeParcelable(objectB, flags);
        dest.writeString(str);
    }

    private A(Parcel in) {
        this.objectB = in.readParcelable(B.class.getClassLoader());
        str = in.readString();
    }

    public static final Parcelable.Creator<A> CREATOR
            = new Parcelable.Creator<A>() {
        public A createFromParcel(Parcel in) {
            return new A(in);
        }

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

Class B

public class B implements Parcelable {
    public String str;

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(str);
    }

    private B(Parcel in) {
        str = in.readString();
    }

    public static final Parcelable.Creator<B> CREATOR
            = new Parcelable.Creator<B>() {
        public B createFromParcel(Parcel in) {
            return new B(in);
        }

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

IMPORTANT: Please note that the order that you write and read the Parcelable object matters. Checkout this answer for more details

Community
  • 1
  • 1
Sami Eltamawy
  • 9,874
  • 8
  • 48
  • 66
3

At Write to parcel

@Override
public void writeToParcel(Parcel parcel, int i) {
    parcel.writeString(name); //if String
    parcel.writeTypedList(assignedEmployees); //if List with custom class, eg. List<AssignedEmployee> assignedEmployees
    parcel.writeParcelable(checkin,i); //if custom class, eg. Checkin checkin;
    }

At Constructor for reading it back

 protected A(Parcel in) {
        name = in.readString();
        assignedEmployees = in.createTypedArrayList(AssignedEmployee.CREATOR);
        checkin = in.readParcelable(Checkin.class.getClassLoader());
    }

where AssignedEmployee, Checkin where custom classes and it should implement Parcelable.

Ebin Joy
  • 2,690
  • 5
  • 26
  • 39
2

Just press ALT+ENTER and replace Parcelable it will implement all the necessary implementation

Dhruv Singh
  • 49
  • 1
  • 2
1

I had the same problem here's a generic version

class Item<T : Parcelable> (val model: T, val index: Int ) : Parcelable {

    constructor(parcel: Parcel) :
        this(parcel.readParcelable(
          Item<T>::model.javaClass.classLoader),
          parcel.readInt()
        ) {}

    override fun writeToParcel(parcel: Parcel?, flag: Int) {
        parcel?.writeParcelable(model, 0)
        parcel?.writeInt(index)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Item<Parcelable>> {
        override fun createFromParcel(parcel: Parcel): Item<Parcelable> {
            return Item(parcel)
        }

        override fun newArray(size: Int): Array<Item<Parcelable>?> {
            return arrayOfNulls(size)
        }
    }
}
Jocky Doe
  • 2,041
  • 4
  • 17
  • 28
0

You can add the Parcelable code generator plugin from prefs, from there you can create the parcelable boiler plate code by doing: - right click class name within model - select generate - select Parcelable

presto - your model will be updated with necessary Parcelable boilerplate code.

GordonW
  • 1,120
  • 2
  • 16
  • 36
0

I was unfortunately using a class (BarEntry) from a 3rd party library which was not able to be parceled. I solved my problem by passing through Intent an array of floats and then reconstructing my BarEntry objects at the receiving end.

This is sub-optimal but it can be a useful process if anyone has a similar circumstance where creating a parcel able object is not an option.

JFreeman
  • 974
  • 1
  • 10
  • 26