Как да сериализирам списък с персонализирани обекти и да го възстановя на RestoreInstanceState в Android?

Здравейте на всички, имам персонализиран обект MasterWithValue (обект със стойност и списък от детайлни обекти, които съм направил), който разширява клас Master (който има само свойство име).

Това е класът MasterWithValue:

public class MasterWithValue extends Master {

private String value;
private List<Detail> detailList;

public MasterWithValue(String masterName, String masterValue) {
    super(masterName);
    this.value = masterValue;
    this.detailList = new ArrayList<Detail>();
}

@Override 
public int getViewType() {
    return super.getViewType();
}

@Override
public View getView(LayoutInflater inflater, View convertView) {
    View view;
    if (convertView == null) {
        view = inflater.inflate(R.layout.statistics_rowlist_master, null);
    }
    else {
        view = convertView;
    }

    TextView MasterEntryName = (TextView) view.findViewById(R.id.statistics_master_name);
    TextView MasterEntryValue = (TextView) view.findViewById(R.id.statistics_master_value);

    MasterEntryName.setText(super.name);
    MasterEntryValue.setText(this.value);

    return view;
}

public String getMasterValue() {
    return value;
}

public List<Detail> getDetailList() {
    return this.detailList;
}

public void addDetailToMaster(Detail detail) {
    this.detailList.add(detail);
}

}

В метода onSaveInstanceState() имам този код:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("master_detail_list", (ArrayList<MasterWithValue>)   
      MasterAndDetailStatistics);
}

Където MasterAndDetailStatistics е списък.

Сега в onRestoreInstanceState опитах този код:

@Override
protected void onRestoreInstanceState(Bundle savedState) {
    super.onRestoreInstanceState(savedState);

    MasterAndDetailStatistics = (List<MasterWithValue>) savedState.getSerializable("master_detail_list");

}

Като получавам предупреждение за безопасност на типа: Безопасност на типа: Непроверено прехвърляне от Serializable към List Как мога да го проверя? Четох, че трябва да внедря интерфейса Parcable, но съм нов в android и нямам представа как да направя това. Какво трябва да направя?


person tonix    schedule 20.03.2014    source източник


Отговори (1)


Има много примери за това как да внедрите парцелиране. Ето го каноничният. Ето отговор от SO.

По принцип вие прилагате метод public void writeToParcel(Parcel out, int flags), където записвате всички полета, които искате да се запазят в стойността out.

След това имплементирайте анонимна реализация на Parcelable.Creator, параметризирана с вашия парцелируем клас. Тази анонимна реализация трябва да бъде наречена CREATOR.

И накрая, направете частен конструктор като този: private MyParcelable(Parcel in). Където четете всички стойности, които сте написали в out обратно в полетата на вашия обект в in.

След това трябва да направите и Detail парцелируем! О, радост!

Трябва да изглежда така:

public class MasterWithDetails implements Parcelable {
    private String value;
    private List<Detail> detailList;

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeString(value);
        out.writeString(getName());
        out.writeTypedList(detailList); //don't forget to make Detail parcelable too!
    }

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

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

    private MasterWithDetails(Parcel in) {
        value = in.readString();
        setName(in.readString());
        detailList = in.createTypedArrayList(Detail.CREATOR);
    }
}
person CorayThan    schedule 20.03.2014
comment
Благодаря за отговора Ако клас MasterWithValue разширява главен клас, те трябва да внедрят интерфейса Parcelable заедно? Имам предвид, че внедрявам интерфейса Parcelable в главния клас и след това в MasterWithValue отменям тези методи, за да запазя и стойността на обекта MasterWithValue, тъй като MasterWithValue има поле за стойност, което главният клас няма. Прав ли съм? - person tonix; 22.03.2014
comment
Също така получавам това, когато се опитвам да извикам writeTypedArrayList(): Методът writeTypedArrayList(List‹Detail›) е недефиниран за типа Parcel. Може би сте възнамерявали да използвате writeTypedList(detailList)? - person tonix; 22.03.2014
comment
Да, вероятно бързах и имах предвид writeTypedList. За класа потомък ще трябва да замените метода writeToParcel (въпреки че с извикване на super.writeToParcel няма да е необходимо да дублирате никаква логика). Конструкторът е частен, така че не може да бъде заменен или извикан и трябва да бъде дублиран. Полето CREATOR е публично и статично, така че не трябва да се променя. Честно казано, парцелирането изглежда доста грозно, когато го използвате с наследяване. Разбира се, мисля, че изглежда грозно на първо място. (Обикновено предпочитам просто да сериализирам класовете си като низове (с JSON) или байтове.) - person CorayThan; 22.03.2014
comment
Благодаря работи! Благодаря за обяснението, беше много ясен и прост! - person tonix; 22.03.2014