Упаковать модель, содержащую коллекцию с пользовательскими объектами

У меня есть этот класс:

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 и MyFoo2 также реализуют Parcelable, но ForeignCollection этого не делает. ForeignCollection — это класс, реализующий интерфейсы: Коллекция, CloseableIterable и Iterable.

Я не могу использовать out.writeList, потому что ForeignCollection не реализует интерфейс списка.


person Fran b    schedule 18.09.2013    source источник
comment
Доступен ли какой-либо конструктор для этой ForeignCollection? Можно ли его воссоздать заново?   -  person sandrstar    schedule 24.09.2013
comment
Нет, это не так. Для создания экземпляра нового объекта ForeignCollection необходимо использовать метод assignEmptyForeignCollection(T parent, String fieldName) ), но это возвращает только пустую коллекцию. Существует другой метод, называемый refresh(T data), который создает экземпляр и заполняет коллекцию значениями БД. Нет смысла его использовать.   -  person Fran b    schedule 24.09.2013


Ответы (2)


Похоже, невозможно поместить эту коллекцию в Parcel. Однако вы все равно можете использовать ввод из этого ответа на основе обычная Сериализация.

Код может выглядеть следующим образом (код взят из приведенной выше ссылки):

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();
    }
}

Да, у него есть некоторые недостатки (например, непроверенное предупреждение), и скорость его будет ниже, чем у обычного Parcelable, однако он должен быть все же быстрее, чем у обычного Seriazable, особенно если MyFoo довольно сложный/большой.

person sandrstar    schedule 24.09.2013

здесь вы можете найти пример, который показывает решение вашей проблемы:

  • Подарок — это объект, который я делаю Parcelable.
  • изображение: считайте, что это единственная переменная в этом классе и что это набор целых чисел
  • метод getImage: возвращает коллекцию Integer (Collection)

Вы можете применить этот шаблон к своим объектам, реализующим коллекцию.

public void writeToParcel(Parcel parcel, int i) {

        List imageList = new ArrayList(getImage());
        parcel.writeList(imageList);
}

public Gift(Parcel source){

        image = source.readArrayList(Integer.class.getClassLoader());

}

P.S. не используйте Collection.sort(imageList) в методе writeToParcel, потому что я бы изменил порядок вашей коллекции, переупорядочив элементы в порядке возрастания.

Лучшие

person Alex Olivieri    schedule 15.11.2014