创建Parcelable ArrayList <customobject>来处理方向更改会导致null </customobject>

时间:2014-11-12 14:26:15

标签: android parcelable

我试图在我的活动中处理方向更改。我有一个由自定义适配器填充的ListView。适配器接受ArrayList<Listing>,其中Listing是我创建的自定义对象。我知道ListView可以工作,但是在方向更改时它会丢失我的数据。

我可能会遗漏一些显而易见的东西但是在完成所有教程和SO帖子之后我仍然无法使其工作。我试图将此传递给新意图。我试图处理方向变化。

这是我实现Parcelable的自定义对象:

package xx.xx.xx.xxxxxxx;

import android.os.Parcel;
import android.os.Parcelable;

public class Listing implements Parcelable {
    private String name;
    private String rating;
    private String cuisines;

    public Listing(){

    }

    public Listing(String name, String rating, String cuisines) {
        this.name = name;
        this.rating = rating;
        this.cuisines = cuisines;
    }



    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRating() {
        return rating;
    }

    public void setRating(String rating) {
        this.rating = rating;
    }

    public String getCuisines() {
        return cuisines;
    }

    public void setCuisines(String cuisines) {
        this.cuisines = cuisines;
    }



    private Listing(Parcel in) {
        // Recreate Object using from the Parcelled String array
        String[] data = new String[3];

        in.readStringArray(data);

        this.name = data[0];
        this.rating = data[1];
        this.cuisines = data[2];
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // Parcel using a String array
        dest.writeStringArray(new String[] {
                this.name,
                this.rating,
                this.cuisines
        });
    }

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

        @Override
        public Listing[] newArray(int size) {
            return new Listing[size];
        }
    };
}

在我的MainActivity中,我有以下内容尝试处理配置更改:

   @Override
    public void onSaveInstanceState(Bundle savedInstanceState){
        super.onSaveInstanceState(savedInstanceState);

        // Save the result ArrayList<Listing>
        savedInstanceState.putParcelableArrayList("result", result);

    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        // Try and restore the List results
        result = savedInstanceState.getParcelableArrayList("result");
        adapter.notifyDataSetChanged();
    }

我没有遇到任何明显的错误,但是当我在代码中调试并添加断点时,我发现savedInstanceStatemParcelledData = null。我认为这意味着我没有正确使用putParcelableArrayList

如果有人可以告诉我如何以更好的方式调试这个问题,那么大有帮助的是什么,这样我就能在问题中提供更好的信息或者自己解决。

由于

更新

当我查看savedInstanceState时,我发现mMap有java.lang.ClassNotFoundException个例外,我希望键值对是。有兴趣解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

为什么你不能这样做? :

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeString(rating);
    dest.writeString(cuisines);
}

private Listing(Parcel in) {
    this.name = in.readString();
    this.rating = in.readString();
    this.cuisines = in.readString();
}

包裹中的订单很重要!你也用

  

putParcelableArrayList

但你使用数组,而不是ArrayList

编辑: 是的,您可以将多个值设置为相同类型(多个字符串,整数,其他Parcelables等),您只需要在重新创建时记住顺序(包中没有键)

编辑2 - 用于评论的ans,有些系数: 也许这样:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeList(new ArrayList<String>(){...});
}

public Listing(Parcel in) {
    ArrayList<Strings> sArrList= new ArrayList<Strings>();
    in.readList(sArrList, getClass().getClassLoader());
    // now sArrListis already filled
}

它可能是您的另一个类的ArrayList,它实现了Parcelable和正确的Parcel保存/恢复/创建者等。结果Object是一个ArrayList是吗? 还有很多谷歌的答案建议用这个arrayList创建分离的parcelable类,并将此对象(如上所述保存在内部拥有的ArrayList中)写入实例Bundle而不是使用普通方法writeParcelableArrayList(不知道为什么,name是如此obvius ...)< / p>

答案 1 :(得分:0)

我想出来了。实际上有两件事在这里发挥作用。

  1. 正确存储和恢复状态。为什么调试器显示nullsjava.lang.ClassNotFoundException我不知道。但是将变量打印到控制台告诉我,状态可以从Bundle中正确恢复。
  2. 在旋转时,配置发生变化,并且(有效地)启动新的活动。生命周期方法都会再次发生。最初我的适配器是在(this)方法中引用当前活动onCreate()创建的。当然,当设备旋转并发生配置更改时,生命周期再次启动,我对适配器的原始引用不再适用于此新活动。调用notifyDataSetChanged()正在更新旧的Activity而不是新的Activity。通过将适配器创建和绑定移动到onResume(),我能够在轮换更改时重新创建ListView!我也不再需要notifyDataSetChanged() onResume()
  3. 希望这有助于其他人!