android 开发之坑系列_实体序列化问题

坑一:实体序列化问题

详情:
java.lang.RuntimeException: Unable to start activity ComponentInfo{app.android.test/app.android.test.activity.MainActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
****Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: ****
at android.os.Parcel.readParcelableCreator(Parcel.java:2154)
at android.os.Parcel.readParcelable(Parcel.java:2104)
实体序列化代码:
`public class HomeDataItem implements Parcelable {
    public BannerGroup bannerGroup;
    public List agility;
    public AppSpecial special;
    public Variety variety;
    public DiscoverBanner banner;
    public int showType;
    public int type;
    public TrafficConfig mTrafficConfig;  

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
         bannerGroup = in.readParcelable(BannerGroup.class.getClassLoader());
        agility = in.createTypedArrayList(Agility.CREATOR);
        special = in.readParcelable(AppSpecial.class.getClassLoader());
        variety = in.readParcelable(Variety.class.getClassLoader());
        banner = in.readParcelable(DiscoverBanner.class.getClassLoader());
        showType = in.readInt();
        mTrafficConfig = in.readParcelable(TrafficConfig.class.getClassLoader());
        type = in.readInt();
    }

    protected HomeDataItem(Parcel in) {
        dest.writeParcelable(bannerGroup, flags);
        dest.writeTypedList(agility);
        dest.writeParcelable(special, flags);
        dest.writeParcelable(variety, flags);
        dest.writeParcelable(banner, flags);
        dest.writeInt(showType);
        dest.writeInt(type);
        dest.writeParcelable(mTrafficConfig, flags);
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public HomeDataItem createFromParcel(Parcel source) {
            return new HomeDataItem(source);
        }

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

从上面不知道大家看出什么门道没,反正当时一脸不知道哪里出了问题,本地测试没有问题,线上就出现问题了,而且还不早,崩溃一下提升到6%,必须解决啊,然后各种查,最后终于发现了是,序列化时,写与读不对称问题,这里我也不知道是咋原因,知道的同学下面留言下(^)!

protected HomeDataItem(Parcel in) {
    bannerGroup = in.readParcelable(BannerGroup.class.getClassLoader());
    agility = in.createTypedArrayList(Agility.CREATOR);
    special = in.readParcelable(AppSpecial.class.getClassLoader());
    variety = in.readParcelable(Variety.class.getClassLoader());
    banner = in.readParcelable(DiscoverBanner.class.getClassLoader());
    showType = in.readInt();
    //原来的位置
    type = in.readInt();
    mTrafficConfig = in.readParcelable(TrafficConfig.class.getClassLoader());
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeParcelable(bannerGroup, flags);
    dest.writeTypedList(agility);
    dest.writeParcelable(special, flags);
    dest.writeParcelable(variety, flags);
    dest.writeParcelable(banner, flags);
    dest.writeInt(showType);
    dest.writeInt(type);
    dest.writeParcelable(mTrafficConfig, flags);
}
重现问题:

重现这个问题即使的应用被系统回收,把设置->开发者选项->不保留活动开关打开,打开测试程序按home键,再打开测试程序就会执行到这句。

相关知识:

Android有两种不同的classloaders:

  1. framework classloader
  2. apk classloader

其中framework classloader知道怎么加载android classes,apk classloader知道怎么加载你自己的代码,而apk classloader继承自framework classloader,所以也知道怎么加载android classes。

而在应用刚启动时,默认class loader是apk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,它就加载不到你自己的代码里面的类,所以会报ClassNotFoundException。

这个是在这边文章中提到的,具体可以看下,但是为什么序列化不按规定会有问题还是不解,在这里先记录着。

你可能感兴趣的:(android)