|
本文主要分析android.os.BadParcelableException: ClassNotFoundException when unmarshalling這個(gè)異常的原因及解決方法,解釋了android的class loader. 一、現(xiàn)象: 應(yīng)用打開,home鍵到后臺(tái),過一段時(shí)間打開,偶現(xiàn)fc,log如下: | E/AndroidRuntime(9085): Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: *.*.*.*.Layout$Config E/AndroidRuntime(9085): at android.os.Parcel.readParcelable(Parcel.java:2077) E/AndroidRuntime(9085): at *.*.*.<init>(Layout.java:105) |
程序中的寫法是 | public Config config; public RowView(Parcel in){ type = in.readString(); interfaceUrl = in.readString(); size = in.readInt(); config = in.readParcelable(null); } |
報(bào)錯(cuò)的語句即為config = in.readParcelable(null); 二、原因分析: 根據(jù)android文檔介紹: readParcelable (ClassLoader loader) loader A ClassLoader from which to instantiate the Parcelable object, or null for the default class loader. 即loader為空時(shí)系統(tǒng)會(huì)采取默認(rèn)的class loader。 Android有兩種不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎么加載android classes,apk classloader知道怎么加載you code,apk classloader繼承自framework classloader,所以也知道怎么加載android classes。 在應(yīng)用剛啟動(dòng)時(shí),默認(rèn)class loader是apk classloader,但在系統(tǒng)內(nèi)存不足應(yīng)用被系統(tǒng)回收會(huì)再次啟動(dòng),這個(gè)默認(rèn)class loader會(huì)變?yōu)閒ramework classloader了,所以對(duì)于自己的類會(huì)報(bào)ClassNotFoundException。 三、解決方法: 將config = in.readParcelable(null);改為config = in.readParcelable(Config.class.getClassLoader()); Config.class.getClassLoader()即為apk classloader, 其中Config.class可以改為你程序中自己寫的任意類,因?yàn)樗麄兺瑯又赶騛pk loader 嘿嘿,試著改為config = in.readParcelable(Activity.class.getClassLoader());你會(huì)發(fā)現(xiàn)依然ClassNotFoundException因?yàn)锳ctivity.class.getClassLoader()指向的是framework classloader 四、如何測試重現(xiàn)這個(gè)問題,方便測試呢: 重現(xiàn)這個(gè)問題即使的應(yīng)用被系統(tǒng)回收,把設(shè)置->開發(fā)者選項(xiàng)->不保留活動(dòng)開關(guān)打開,打開測試程序按home鍵,再打開測試程序就會(huì)執(zhí)行到這句。 如果你是在onSaveInstanceState中保存 savedInstanceState.putParcelable(key, value),則需要設(shè)置Bundle的class loader,如下: savedInstanceState.setClassLoader(getClass().getClassLoader()); PS: (1)、readParcelableArray(ClassLoader loader), readParcelable, readArray,readArrayList, readBundle, readHashMap, readParcelable, readSparseArray, readValue, readList, readMap也有可能報(bào)上面的異常
|