2

There is an interface DrawingElement (extending Parcelable) with multiple implementations. There is a field List<DrawingElement> elements in another class, which implements Parcelable. So the List should be written to the Parcel, but the method for reading Parcelable ArrayList requires a concrete class for referencing the concrete implementation of a Creator and this is not working: in.createTypedArrayList(DrawingElement.CREATOR).

public interface DrawingElement extends Parcelable {
}

public class FirstDrawingElementImpl implements DrawingElement {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // done easily.
    }
}

public class SecondDrawingElementImpl implements DrawingElement {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // done easily.
    }
}

public class DrawingElementsContainer implements Parcelable {
    private List<DrawingElement> elements;

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO:
    }
}

Any suggestions?

UPDATE:

If I had to use the @pskink suggestion, I had to do weird casting like:

protected Drawing(Parcel in) {
    DrawingElement[] parcelables = (DrawingElement[]) in.readParcelableArray(DrawingElement.class.getClassLoader());
    elements = new ArrayList<>(Arrays.asList(parcelables));
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeParcelableArray(elements.toArray(new Parcelable[elements.size()]), flags);
}

dest.writeList(elements) is the obvious decision, but I got confused by passing an interface classloader.

Galya
  • 6,294
  • 6
  • 27
  • 45

1 Answers1

0

Use below code to define your class. parcel.readArrayList method is used to read the list from the parcel and parcel.wrtieList method is used to write list to the parcel. Refer this answer.

public class DrawingElementsContainer implements Parcelable {

    private ArrayList<DrawingElement> elements;

    public DrawingElementsContainer(Parcel in) {
        elements=in.readArrayList(DrawingElement.class.getClassLoader());
    }

    public ArrayList<DrawingElement> getElements() {
        return elements;
    }

    public void setElements(ArrayList<DrawingElement> elements) {
        this.elements = elements;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public DrawingElementsContainer()
    {

    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(elements);
    }
    public static final Parcelable.Creator<DrawingElementsContainer> CREATOR
            = new Parcelable.Creator<DrawingElementsContainer>() {
        public DrawingElementsContainer createFromParcel(Parcel in) {
            return new DrawingElementsContainer(in);
        }

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

Hope it might help you

Community
  • 1
  • 1
Amrut Bidri
  • 6,276
  • 6
  • 38
  • 80
  • Can you please give any explanation on how the interface class loader works for resolving an implementation class. This is what confused me. – Galya Jan 30 '17 at 10:10
  • you can class instead of interface (for DrawingElement) here to make it work for you. is it necessary for you to use interface only? – Amrut Bidri Jan 30 '17 at 10:12
  • Yes, I do, this is the point of the question. The interesting part is that your code actually works. Some magic happens in the background, that I don't fully comprehend. – Galya Jan 30 '17 at 10:16
  • Its not a magic. It is the way of implementation. It works based on our implementations – Amrut Bidri Jan 30 '17 at 10:23