Чтение ArrayList в Parcelable

У меня есть класс SuperMedia, который реализует Parcelable. Одно из полей класса является потомком ArrayList. Когда я создаю Bundle и пытаюсь передать объект «SuperMedia» из одного действия в другое, все поля передаются нормально, за исключением «дочерних элементов» ArrayList, которые каждый раз отображаются как пустые.

В моем первом действии я делаю:

 Bundle a = new Bundle();
 a.putParcelable("media",media); //media is an object of type "SuperMedia" and all the "children" have been initialized and added to the array
 final Intent i = new Intent("com.tv.video.subcategories");
 i.putExtra("subcategories", a);

В моем втором действии я делаю:

  Intent i = getIntent();
  Bundle secondBun = i.getBundleExtra("subcategories");
  SuperMedia media = secondBun.getParcelable("media"); //For some reason the ArrayList"children" field shows up as empty. 

Я не уверен, почему это происходит. Если кто-нибудь может направить меня на правильный путь, который был бы очень признателен. Ниже мой класс SuperMedia, кстати.

public class SuperMedia implements Parcelable{

public URI mthumb;
public String mTitle;
public ArrayList<SuperMedia> children = new ArrayList(); 

public SuperMedia(URI thumb, String title) {
    this.mthumb = thumb;
    this.mTitle = title;
}


@Override
public void writeToParcel(Parcel dest, int flags) {
    // TODO Auto-generated method stub
    dest.writeString(mTitle);
    dest.writeString(mthumb.toString());
    dest.writeTypedList(children);

}

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

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

private SuperMedia(Parcel in) {
    mTitle = in.readString();
    try {
        mthumb = new URI(in.readString());
    } catch (URISyntaxException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    in.readTypedList(children, SuperMedia.CREATOR);

}

public SuperMedia(){

}

}


person aafonso1991    schedule 08.05.2014    source источник
comment
children содержит экземпляр SuperMedia? или есть его потомки?   -  person njzk2    schedule 08.05.2014
comment
@njzk2 содержит потомков   -  person aafonso1991    schedule 08.05.2014
comment
тогда он не может работать, так как SuperMedia.CREATOR не знает, как их распаковать.   -  person njzk2    schedule 08.05.2014
comment
Ваш код, кажется, должен работать. Я не уверен, но попробуйте изменить public ArrayList<SuperMedia> children = new ArrayList(); на public List<SuperMedia> children = new ArrayList(); .   -  person erakitin    schedule 08.05.2014
comment
@erakitin: это ничего не меняет, поскольку ArrayList — это список. Кроме того, фактическая проблема здесь в том, что SuperMedia implements Parcelable, но это не работает ни для чего extends SuperMedia, потому что SuperMedia.CREATOR может вызывать только new SuperMedia(in)   -  person njzk2    schedule 08.05.2014
comment
@ njzk2 Я пробовал понижать приведение, и мой дочерний класс Subcategory перезаписал все методы Parcelable, но в дочернем классе выполнение in.readTypedList(children, Subcategory.CREATOR) дает мне ошибку   -  person aafonso1991    schedule 08.05.2014
comment
да, потому что ваш список по-прежнему имеет тип List<SuperMedia>, не так ли?   -  person njzk2    schedule 09.05.2014
comment
(Parcelable далек от оптимального/очевидного, когда речь идет о наследовании. В большинстве случаев я бы рассматривал не передачу объекта, а ссылку на запись в базе данных или что-то в этом роде)   -  person njzk2    schedule 09.05.2014
comment
Вы должны читать в том же порядке, что и писать, и это действительно неправильно. Не сериализуемый ответ.   -  person danny117    schedule 09.05.2014
comment
@danny117 Я делал это   -  person aafonso1991    schedule 09.05.2014


Ответы (2)


Если вы хотите просто передать объект через намерение, вы можете сделать SuperMedia Serializable без необходимости использовать Parcelable.

public class SuperMedia implements Serializable{...}

поставь как

Bundle a = new Bundle(); a.putSerializable("media",media);

и мы получаем это как.

Intent i = getIntent();
Bundle secondBun = i.getBundleExtra("subcategories");
SuperMedia media = (SuperMedia)secondBun.getSerializable("media");

если вам действительно нужен Parcelable, может он вам поможет. Arraylist в делимом объекте

person Pradeep Yaduvanshy    schedule 08.05.2014
comment
Разве Parcelable и Serializable не делают одно и то же? Моя проблема в том, что мои дочерние элементы arrayList всегда отображаются как пустые во втором действии после того, как я передаю его. - person aafonso1991; 08.05.2014
comment
@Pradeep Parcelable намного быстрее и лучше оптимизирован для IPC, поэтому он рекомендуется Android. (Люди не просто добавляют новые способы делать то же самое только для того, чтобы возиться с головами людей) - person njzk2; 08.05.2014
comment
@PradeepYaduvanshy: однако, учитывая простоту использования Serializable по сравнению с Parcelable, в данном случае это может быть хорошей альтернативой, если есть много потомков SuperMedia - person njzk2; 08.05.2014
comment
@PradeepYaduvanshy Реализация Serializable, а не Parcelable решила проблему. Большое вам спасибо за вашу помощь - person aafonso1991; 09.05.2014

Используйте пакет putParcellableArrayList для хранения объекта SuperMedia.

Bundle args = new Bundle();
args.putParcelableArrayList("media", "media");

и для восстановления

getArguments().getParcelableArrayList("media");

Таким образом, пакет сохранит ваши объекты списка так, как они реализованы в экземпляре, подлежащем разделению. Кроме того, помните об использовании только ArrayList, другие подклассы List не поддерживаются.

person Gökhan Barış Aker    schedule 08.05.2014
comment
это должно быть args.putParcelable, потому что медиа — это объект, а не ArrayList. - person aafonso1991; 08.05.2014