Как написатьToParcel ArrayList интерфейса

Существует интерфейс DrawingElement (расширяющий Parcelable) с несколькими реализациями. В другом классе есть поле List<DrawingElement> elements, которое реализует Parcelable. Таким образом, List должен быть записан в Parcel, но метод чтения Parcelable ArrayList требует конкретного класса для ссылки на конкретную реализацию Creator, а это не работает: 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:
    }
}

Какие-либо предложения?

ОБНОВЛЕНИЕ:

Если бы мне пришлось использовать предложение @pskink, мне пришлось бы делать странные приведения, например:

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) — очевидное решение, но я запутался, передав интерфейсный загрузчик классов.


person Galya    schedule 27.01.2017    source источник
comment
поможет увидеть, как вы его реализуете   -  person ootinii    schedule 27.01.2017
comment
зачем тебе этот Parcelable?   -  person pskink    schedule 27.01.2017
comment
@ootinii, если бы я знал, как реализовать запись списка интерфейсов в посылку, вообще не было бы вопроса.   -  person Galya    schedule 28.01.2017
comment
@pskink, мне это нужно в методе onSaveInstanceState.   -  person Galya    schedule 28.01.2017
comment
интерфейс - это код, вам нужно сохранить какое-то состояние: это ваши данные, а не код   -  person pskink    schedule 28.01.2017
comment
@pskink, у вас есть лучший способ работы с данными в Android, чем использование кода?   -  person Galya    schedule 28.01.2017
comment
Итак, вы хотите написать объект Parcelable, а не какой-то абстрактный интерфейс, затем используйте writeParcelableArray/readParcelableArray   -  person pskink    schedule 29.01.2017


Ответы (1)


Используйте приведенный ниже код, чтобы определить свой класс. Метод parcel.readArrayList используется для чтения списка из посылки, а метод parcel.wrtieList используется для записи списка в посылку. см. этот ответ.

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];
        }
    };
}

Надеюсь, это может помочь вам

person Amrut Bidri    schedule 30.01.2017
comment
Не могли бы вы объяснить, как работает загрузчик классов интерфейса для разрешения класса реализации. Вот это меня смутило. - person Galya; 30.01.2017
comment
вы можете использовать класс вместо интерфейса (для DrawingElement), чтобы он работал на вас. Вам необходимо использовать только интерфейс? - person Amrut Bidri; 30.01.2017
comment
Да, знаю, в этом суть вопроса. Самое интересное, что ваш код действительно работает. На заднем плане происходит какая-то магия, которую я не совсем понимаю. - person Galya; 30.01.2017
comment
Это не магия. Это способ реализации. Он работает на основе наших реализаций - person Amrut Bidri; 30.01.2017