how to properly implement Parcelable with an ArrayList<Parcelable>?

57,197

Solution 1

You almost got it !

You just need to do :

public void writeToParcel(Parcel out, int flags) {
    out.writeString(_mac);
    out.writeString(_pan);
    out.writeInt(_band);
    out.writeSerializable(_lqis);
    out.writeTypedList(_devices);
}

private ZigBeeNetwork(Parcel in) {
    _mac = in.readString();
    _pan = in.readString();
    _band = in.readInt();
    _lqis = (ArrayList<Integer>) in.readSerializable();
    in.readTypedList(_devices, ZigBeeDev.CREATOR);
}

That's all!

For your list of Integer, you can also do :

out.writeList(_lqis);
_lqis = new ArrayList<>();
in.readList(_lqis Integer.class.getClassLoader());

It should work.

Solution 2

In my case in.readTypedList(_devices, ZigBeeDev.CREATOR); gave me a NullPointerException on _devices. So I used this:

_devices = in.createTypedArrayList(ZigBeeDev.CREATOR);

Solution 3

You should use writeList(List l) for your list of integers and writeTypedList(List val) for the list of ZigBeeDevices

Solution 4

In constructor you should use

_lqis = in.createTypedArrayList(ZigBeeDev.CREATOR);

And in "writeToParcel" use

out.writeTypedList(_lqis);
Share:
57,197

Related videos on Youtube

gnychis
Author by

gnychis

Just a student

Updated on July 05, 2022

Comments

  • gnychis
    gnychis almost 2 years

    I am having trouble making my class Parcelable. The trouble is, I am trying to write to the parcel a member in the class which is an ArrayList<Parcelable> object. The ArrayList is Serializable, and the objects (ZigBeeDev) in the list are Parcelable.

    Here is the relevant code:

    package com.gnychis.coexisyst;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class ZigBeeNetwork implements Parcelable {
    
        public String _mac;             // the source address (of the coordinator?)
        public String _pan;             // the network address
        public int _band;               // the channel
        ArrayList<Integer> _lqis;       // link quality indicators (to all devices?)
        ArrayList<ZigBeeDev> _devices;  // the devices in the network
    
        public void writeToParcel(Parcel out, int flags) {
            out.writeString(_mac);
            out.writeString(_pan);
            out.writeInt(_band);
            out.writeSerializable(_lqis);
            out.writeParcelable(_devices, 0);  // help here
        }
    
        private ZigBeeNetwork(Parcel in) {
            _mac = in.readString();
            _pan = in.readString();
            _band = in.readInt();
            _lqis = (ArrayList<Integer>) in.readSerializable();
            _devices = in.readParcelable(ZigBeeDev.class.getClassLoader());  // help here
        }
    
        public int describeContents() {
            return this.hashCode();
        }
    
        public static final Parcelable.Creator<ZigBeeNetwork> CREATOR = 
                new Parcelable.Creator<ZigBeeNetwork>() {
            public ZigBeeNetwork createFromParcel(Parcel in) {
                return new ZigBeeNetwork(in);
            }
    
            public ZigBeeNetwork[] newArray(int size) {
                return new ZigBeeNetwork[size];
            }
        };
    
        //...
    }
    

    I have marked two spots "// help here" to understand how to properly write to the parcel and how to reconstruct it. If ZigBeeDev is Parcelable (properly tested), how do I do this properly?

  • gatlingxyz
    gatlingxyz about 10 years
    For future reference, and I'm not sure if it's a typo that no one has noticed, but ZigBeeDev.Creator should be ZigBeeDev.CREATOR. I got an error every time until I realized there were two different creators I could use in my own project.
  • AlexAndro
    AlexAndro almost 10 years
    @NitroG42 The second approach for read list results into cannot convert from void to ArrayList<Integer>
  • sgarman
    sgarman over 9 years
    I also needed to instantiate the array before as well, example my code would look like: _devices = new ArrayList<ZigBeeDev>(); in.readTypedList(_devices, ZigBeeDev.Creator);
  • rf43
    rf43 over 8 years
    fwiw - the reason you were receiving a NPE is because if you use in.readTypedList() you need to create a new ArrayList() first and then pass that to the in.readTypedList(yourNewArrayList, YourObj.CREATOR) otherwise it will only be trying to put the data into a null list.
  • osrl
    osrl over 8 years
    Yes, that's correct. I've read the source code before I used it. Thank you for the extra information which I forgot to write.
  • Ajit Kumar Dubey
    Ajit Kumar Dubey over 8 years
    @osrl when we follow your solution got exception java.lang.OutOfMemoryError: Failed to allocate a 13893804 byte allocation with 11004100 free bytes and 10MB until OOM
  • osrl
    osrl about 8 years
    Does your array hold files or something big? @Ajit
  • crubio
    crubio about 8 years
    @sgarman There's no need to instantiate the array cause then you get the warning: Explicit type argument ZigBeeDev can be replaced with <> This inspection reports all new expressions with type arguments which can be replaced with diamond type <>
  • Eido95
    Eido95 over 7 years
    Confirm to be working with generic Hashtable that uses primitives types (including String) for either of his keys or values.