编组和解组List <list <t>&gt;使用Android的Parcel </list <t>

时间:2014-03-09 05:20:10

标签: android marshalling unmarshalling parcelable

我尝试在实现ClassNotFoundException的自定义类中解组List<List<LatLng>时得到Parcelable。我该如何摆脱这种例外?

这是我的班级:

public class Country implements Parcelable {

    public static final Parcelable.Creator<Country> CREATOR = new Creator<Country>() {

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

        @SuppressWarnings("unchecked")
        @Override
        public Country createFromParcel(Parcel source) {
            Country country = new Country();
            country.name = source.readString();
            country.borders = source.readArrayList(Country.class
                    .getClassLoader());
            return country;
        }
    };

    public String name;

    public List<List<LatLng>> borders;

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

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

}

这是我的logcat:

03-08 22:09:43.749: E/AndroidRuntime(16991): FATAL EXCEPTION: main
03-08 22:09:43.749: E/AndroidRuntime(16991): java.lang.RuntimeException: Unable to start activity ComponentInfo{codeguru.worldtour/codeguru.worldtour.MainActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: codeguru.worldtour.Country
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1654)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1670)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2844)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.access$1600(ActivityThread.java:117)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Looper.loop(Looper.java:130)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.main(ActivityThread.java:3695)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at java.lang.reflect.Method.invokeNative(Native Method)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at java.lang.reflect.Method.invoke(Method.java:507)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at dalvik.system.NativeStart.main(Native Method)
03-08 22:09:43.749: E/AndroidRuntime(16991): Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: codeguru.worldtour.Country
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readParcelable(Parcel.java:1958)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readValue(Parcel.java:1846)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readListInternal(Parcel.java:2092)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readArrayList(Parcel.java:1536)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readValue(Parcel.java:1867)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Parcel.readMapInternal(Parcel.java:2083)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Bundle.unparcel(Bundle.java:208)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Bundle.getBundle(Bundle.java:1078)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at ekg.a(SourceFile:74)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at maps.e.al.a(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at maps.e.bj.a(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at eir.onTransact(SourceFile:66)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.os.Binder.transact(Binder.java:279)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.maps.internal.IMapViewDelegate$a$a.onCreate(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.maps.MapView$a.onCreate(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.dynamic.a$3.b(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.dynamic.a$1.a(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.maps.MapView$b.eb(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.maps.MapView$b.a(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.dynamic.a.a(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.dynamic.a.onCreate(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at com.google.android.gms.maps.MapView.onCreate(Unknown Source)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at codeguru.worldtour.MainActivity.onCreate(MainActivity.java:63)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
03-08 22:09:43.749: E/AndroidRuntime(16991):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1618)
03-08 22:09:43.749: E/AndroidRuntime(16991):    ... 12 more

编组:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putParcelableArrayList(COUNTRIES_KEY, countries);
    savedInstanceState.putInt(COUNTRIES_INDEX_KEY, countryIndex);
}

解组(onCreate()):

    if (savedInstanceState != null) {
        countryIndex = savedInstanceState.getInt(COUNTRIES_INDEX_KEY, -1);
        countries = savedInstanceState
                .getParcelableArrayList(COUNTRIES_KEY);
    }

4 个答案:

答案 0 :(得分:1)

编辑:

确保LatLng实施Parcelable。否则,当必须编组/解组Country时,活动将不知道如何编组和取消编组(这就是为什么您可能会收到错误:The inferred type List<LatLng> is not a valid substitute for the bounded parameter <T extends Parcelable>

这应该有用 - 创建一个扩展ArrayList<LatLng>的类。我们的想法是使用CREATOR ParcelableArrayList(下面的课程)来创建您的列表。它只有在您将列表实例化为ArrayList时才会起作用(如您提到的另一个答案)。

public class ParcelableArrayList extends ArrayList<LatLng> implements 
    Parcelable {

public ParcelableArrayList(){
    super();
}

protected ParcelableArrayList(Parcel in) {
    in.readList(this, LatLng.class.getClassLoader());
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeList(this);
}   

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

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

现在,在Country课程中:

public class Country implements Parcelable {

public static final Parcelable.Creator<Country> CREATOR = new Creator<Country>() {

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

    @SuppressWarnings("unchecked")
    @Override
    public Country createFromParcel(Parcel source) {
        return new Country(in);
    }
};

public String name;
public List<ParcelableArrayList> borders;

public Country(Parcel source) {

    country.name = source.readString();

    country.borders = new ArrayList<ParcelableArrayList()>();
    country.borders = source.readTypedList(ParcelableArrayList.CREATOR);

}

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

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

}

编辑2:

好的,请尝试使用Parcel#readTypedList(),而不是使用Parcel#readList()阅读。所以替换:

    country.borders = new ArrayList<ParcelableArrayList()>();
    country.borders = source.readTypedList(ParcelableArrayList.CREATOR);

    country.borders = new ArrayList<ParcelableArrayList()>();
    country.borders = source.readList(country.borders, ParcelableArrayList.class.getClassLoader());

我在自己的应用程序中对此进行了测试,并且没有编译时间或运行时错误(据我所见)。

答案 1 :(得分:0)

点击此处的主题以及对答案的所有评论:https://stackoverflow.com/a/4915219/693752

可能有趣的是:

  • 将边框声明为数组列表(不是列表)
  • 使用parcel.writeTypedList(List)编写边框列表
  • 使用parcel.createTypedArrayList从包裹中读取它。看起来readArrayList很难处理。

答案 2 :(得分:0)

添加一个构造函数,该构造函数将parcel作为参数并将一个Creator添加到您的类中。

public Country(Parcel source) {
    country.name = source.readString();
    country.borders = source.readArrayList(Country.class
                .getClassLoader());
}

@SuppressWarnings("rawtypes")
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
    public Country createFromParcel(Parcel in) {
        return new Country(in);
    }

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

答案 3 :(得分:0)

我通过将List<List<LatLng>>分成List<CustomClass>来解决这个问题 其中CustomClass extends ArrayList<LatLng>>

这是我的CustomClass代码

import java.util.ArrayList;

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

public class Lister extends ArrayList<AlertEvaluation> implements Parcelable {

    protected Lister(Parcel in) {
        this.addAll(in.readArrayList(AlertEvaluation.class.getClassLoader()));
    }

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

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

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

    @Override public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeList(this);
    }
}