如何将自定义Parcelable类添加至系统ClassLoader,全局解决Bundle异常?
全局解决自定义Parcelable的ClassLoader问题
老哥,我太懂你每次手动给Bundle设置ClassLoader的烦躁了——重复操作简直是浪费生命!确实有办法在应用层面一次性搞定这个问题,不用再每次都折腾。
先给你说下问题根源:系统在处理Bundle的序列化/反序列化时,有时候会默认使用系统类加载器,但你的自定义Parcelable类(A和B)是由应用自己的类加载器加载的,这就导致解包时找不到类,抛出BadParcelableException: ClassNotFoundException when unmarshalling。
下面给你两个全局解决方案,任选其一就行:
方案1:用Application的Activity生命周期回调(推荐,无需修改Activity继承)
直接在自定义Application里注册一个全局的Activity生命周期监听,自动给所有Activity的Bundle设置ClassLoader:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { // 恢复状态前给Bundle设置应用类加载器 if (savedInstanceState != null) { savedInstanceState.setClassLoader(activity.getClassLoader()); } } @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { // 保存状态时提前设置好类加载器 outState.setClassLoader(activity.getClassLoader()); } // 其他生命周期方法留空即可 @Override public void onActivityStarted(@NonNull Activity activity) {} @Override public void onActivityResumed(@NonNull Activity activity) {} @Override public void onActivityPaused(@NonNull Activity activity) {} @Override public void onActivityStopped(@NonNull Activity activity) {} @Override public void onActivityDestroyed(@NonNull Activity activity) {} }); } }
记得在AndroidManifest.xml里把Application指定为这个自定义类:
<application android:name=".MyApp" ...> ... </application>
方案2:用基类Activity(适合已有统一基类的项目)
如果你的项目已经有一个所有Activity都继承的基类,直接在基类里重写状态保存和恢复的方法,统一设置ClassLoader:
public class BaseActivity extends AppCompatActivity { @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // 先给Bundle设置类加载器,再调用父类方法 if (savedInstanceState != null) { savedInstanceState.setClassLoader(getClassLoader()); } super.onRestoreInstanceState(savedInstanceState); } @Override protected void onSaveInstanceState(Bundle outState) { // 保存状态前设置类加载器 outState.setClassLoader(getClassLoader()); super.onSaveInstanceState(outState); } }
之后所有Activity继承这个基类,就再也不用手动处理ClassLoader的问题了。
这两个方案都能从应用层面全局解决问题,以后不管是屏幕旋转还是其他需要保存Bundle的场景,都不会再出现那个烦人的ClassNotFoundException了。
内容的提问来源于stack exchange,提问作者Andriy Antonov
相关产品推荐
相关产品推荐

