javaandroiddesign-patternsinheritanceparcelable

Abstract class as parcelable


Basicly I have the following structure in my app:

uml of my app

It would be straightforward to implement such a structure without the abstract class ProjectItem, but in this case I don't know how to implement this.

The abstract class ProjectItem needs a CREATOR as it should be parcelable. (like in.readTypedList(mProjectItems, ProjectItem.CREATOR); within the constructor Project(Parcel in))

But in fact, the CREATOR can only be implemented in its derived classes for logical reasons.

So, how to implement this structure in order to keep the class Project parcelable??

Edit

This is what one of the constructors of Project looks like:

private Project(Parcel in) {
    in.readTypedList(mProjectItems, ProjectItem.CREATOR);
}

But as I already said, ProjectItem shouldn't have to implement a CREATOR


Solution

  • The selected answer (from evertvandenbruel's post) has a bug in it. The correct code must account for parceling when just one of the subclasses is being parceled, not just a list of the superclass objects.

    All the other code should be the same, the key is that you MUST read in the type variable in ALL creators (see code below). Otherwise there will be issues with the ordering when trying to unparcel a subclass object

    Ex:

    package com.example.parcelable_example.model;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class Cat extends Animal{
    
        public Cat(String name){
            super(name, "Cat");
        }
    
        public int describeContents() {
            return 0;
        }
    
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(getType());
            super.writeToParcel(dest, flags);
        }
    
        public Cat(Parcel source) {
            super(source);      
        }
    
        public static final Parcelable.Creator<Cat> CREATOR = new Parcelable.Creator<Cat>() {
            public Cat createFromParcel(Parcel in) {
                /** DO NOT FORGET THIS!!! **/
                type = in.readString();
                return new Cat(in);
            }
    
            public Cat[] newArray(int size) {
                return new Cat[size];
            }
        };
    
    }