在不使用数据库的前提下,如何保存并恢复一个自定义的ArrayList?
在线获取JSON格式的数据,并存储到一个ArrayList。由于应用被系统在后台关闭时,这个ArrayList会被清空,导致用户从“最近使用的应用”列表返回应用时,会抛出空指针异常。所以我们需要在onSavedInstanceState中保存这个ArrayList,并在用户返回时检查ArrayList是否为空,如果为空就应该恢复之前保存的数据。
自定义的Recipe类结构如下:
public class Recipe {
@SerializedName("ingredients")
@Expose
private ArrayList<Ingredient> ingredients;
@SerializedName("name")
@Expose
private String name;
@SerializedName("steps")
@Expose
private ArrayList<Step> steps;
///...
注意其中的ingredients和steps是两个自定义的ArrayList,因此无法直接存储在Bundle中。Ingredient和Step两个类的结构如下:
public class Ingredient {
@SerializedName("measure")
@Expose
private String measure;
@SerializedName("ingredient")
@Expose
private String ingredient;
@SerializedName("quantity")
@Expose
private String quantity;
///...
public class Step {
@SerializedName("shortDescription")
@Expose
private String shortDescription;
@SerializedName("description")
@Expose
private String description;
@SerializedName("videoURL")
@Expose
private String videoURL;
@SerializedName("thumbnailURL")
@Expose
private String thumbnailURL;
///...
Ingredient和Step是两个只包含String对象的类,可以实例化Parcelable接口,并在onSaveInstanceState中使用putParcelableArrayList方法来存储ArrayList。
以Ingredient类为例:
public class Ingredient implements Parcelable {
@SerializedName("measure")
@Expose
private String measure;
@SerializedName("ingredient")
@Expose
private String ingredient;
@SerializedName("quantity")
@Expose
private String quantity;
private Ingredient(Parcel in) {
measure = in.readString();
ingredient = in.readString();
quantity = in.readString();
}
public static final Creator<Ingredient> CREATOR = new Creator<Ingredient>() {
@Override
public Ingredient createFromParcel(Parcel in) {
return new Ingredient(in);
}
@Override
public Ingredient[] newArray(int size) {
return new Ingredient[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(measure);
dest.writeString(ingredient);
dest.writeString(quantity);
}
///...
实例化Parcelable接口后,可以在onSaveInstanceState中储存数据:
@Override
protected void onSaveInstanceState(Bundle outState) {
///...
//把ArrayList存进Bundle中
outState.putInt(NUMBER_OF_RECIPES, RecipeList.recipes.size());
for (int i = 0; i < RecipeList.recipes.size(); i++) {
outState.putParcelableArrayList(RecipeList.sIngredientsLabel + i,
RecipeList.recipes.get(i).getIngredients());
outState.putString(RecipeList.sNamesLabel + i, RecipeList.recipes.get(i).getName());
outState.putParcelableArrayList(RecipeList.sStepsLabel + i,
RecipeList.recipes.get(i).getSteps());
}
super.onSaveInstanceState(outState);
}
随后,我们可以在onCreate或者onRestoreInstanceState方法中恢复数据:
@Override
protected void onCreate(Bundle savedInstanceState) {
///...
//假如RecipeList.recipes为空,则尝试从Bundle中恢复数据
if (savedInstanceState != null && savedInstanceState.containsKey(NUMBER_OF_RECIPES)) {
if (RecipeList.recipes == null || RecipeList.recipes.size() == 0) {
int numberOfRecipes = savedInstanceState.getInt(NUMBER_OF_RECIPES);
for (int i = 0; i < numberOfRecipes; i++) {
ArrayList<Ingredient> ingredients =
savedInstanceState
.getParcelableArrayList(RecipeList.sIngredientsLabel + i);
String name = savedInstanceState.getString(RecipeList.sNamesLabel + i);
ArrayList<Step> steps =
savedInstanceState
.getParcelableArrayList(RecipeList.sStepsLabel + i);
Recipe recipe = new Recipe(ingredients, name, steps);
RecipeList.recipes.add(recipe);
}
}
}