Search code examples
androidormliteparcelableparcel

Parcel a model that contains a collection with custom objects


I have this class:

public class Foo implements Parcelable {
    private int id;
    private MyFoo myFoo
    private ForeignCollection<MyFoo2> myFoo2s;

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(id);
        out.writeParcel(myFoo, flags);
        out.write //How can I write the ForeignCollection?
    } 

    public Foo(Parcel in) {
        id = in.readInt();
        myFoo = in.readParcelable(getClass().getClassLoader())
        myFoo2s = // How can I read the ForeignCollection?
    }

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

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

MyFoo and MyFoo2 classes implements Parcelable too, but ForeignCollection doesn't do it. ForeignCollection is a class that implements the interfaces: Collection, CloseableIterable and Iterable.

I cannot use out.writeList because ForeignCollection doesn't implement List interface.


Solution

  • Looks like it's impossible to put that collection to Parcel. However, You can still use input from this answer based on normal Serialization.

    The code could look like the following (code is adopted from above link):

    public static class SerializationUtility {
        /** Read the object from Base64 string. */
        static Object fromString(String s) throws IOException ,
                ClassNotFoundException {
            final byte [] data = Base64.decode(s, Base64.DEFAULT);
            final ObjectInputStream ois = new ObjectInputStream(
                    new ByteArrayInputStream(data));
            final Object o  = ois.readObject();
    
            ois.close();
    
            return o;
        }
    
        /** Write the object to a Base64 string. */
        static  String toString(Serializable o) throws IOException {
            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
            final ObjectOutputStream oos = new ObjectOutputStream(baos);
    
            oos.writeObject(o);
            oos.close();
            return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
        }
    }
    
    public static class Foo implements Parcelable {
        private int id;
        private MyFoo myFoo;
        private ForeignCollection<MyFoo2> myFoo2s;
    
        public void writeToParcel(Parcel out, int flags) {
            out.writeInt(id);
            out.writeParcelable(myFoo, flags);
    
            // Actually, this should be always true
            if (myFoo2s instanceof Serializable) {
                try {
                    out.writeString(SerializationUtility.toString((Serializable) myFoo2s));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        @SuppressWarnings("unchecked")
        public Foo(Parcel in) {
            id = in.readInt();
            myFoo = in.readParcelable(getClass().getClassLoader());
            try {
                myFoo2s = (ForeignCollection<MyFoo2>) SerializationUtility.fromString(in.readString());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() {
            public Foo createFromParcel(Parcel in) {
                return new Foo(in);
            }
    
            public Foo[] newArray(int size) {
                return new Foo[size];
            }
        };
    
        @Override
        public int describeContents() {
            return hashCode();
        }
    }
    

    Yes, it has some downsides (like unchecked warning) and speed of it will be slower than normal Parcelable, however it should be still faster than normal Seriazable especially if MyFoo is quite complex / big.