安卓;java.lang.RuntimeException:Parcelable遇到ClassNotFoundException读取可序列化对象;

安卓;java.lang.RuntimeException:Parcelable遇到ClassNotFoundException读取可序列化对象;,java,android,android-intent,enums,classnotfoundexception,Java,Android,Android Intent,Enums,Classnotfoundexception,我有一个Android应用程序,我在其中添加了一个枚举: public enum RootNavigationOption { HOME(R.string.home, R.drawable.ic_home), SETTINGS(R.string.settings, R.drawable.ic_settings), LOGOUT( R.string.logout_label, R.drawable.ic_logout); private int navig

我有一个Android应用程序,我在其中添加了一个枚举:

public enum RootNavigationOption {
    HOME(R.string.home, R.drawable.ic_home), SETTINGS(R.string.settings, R.drawable.ic_settings), LOGOUT(
            R.string.logout_label, R.drawable.ic_logout);

    private int navigationOptionLabelResId;
    private int navigationOptionImageResId;

    private RootNavigationOption(int navigationOptionLabelResId, int navigationOptionImageResId) {

        this.navigationOptionLabelResId = navigationOptionLabelResId;
        this.navigationOptionImageResId = navigationOptionImageResId;
    }

    public int getNavigationOptionLabelResId() {
        return navigationOptionLabelResId;
    }

    public int getNavigationOptionImageResId() {
        return navigationOptionImageResId;
    }

    public static int getValuePosition(RootNavigationOption filterOption) {
        int idx = 0;
        for (RootNavigationOption navigationOptionIter : values()) {
            if (navigationOptionIter.equals(filterOption)) {
                return idx;
            }
            idx++;
        }
        return 0;
    }
}
我放入这个枚举并将其放入几个意图包中,以便与我的主要活动进行通信。我的解决方案中已经有一个这样的
enum
,这不会导致任何问题。但是,当我在定义了这个新的
enum
的情况下运行应用程序时,它会立即崩溃:

 java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.pack1.pack2.pack3.helpers.RootNavigationOption)
    at android.os.Parcel.readSerializable(Parcel.java:2219)
    at android.os.Parcel.readValue(Parcel.java:2064)
    at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
    at android.os.Bundle.unparcel(Bundle.java:249)
    at android.os.Bundle.getString(Bundle.java:1118)
    at android.app.ActivityOptions.<init>(ActivityOptions.java:310)
    at com.android.server.am.ActivityRecord.updateOptionsLocked(ActivityRecord.java:668)
    at com.android.server.am.ActivityStack.startActivityLocked(ActivityStack.java:1778)
    at com.android.server.am.ActivityStackSupervisor.startActivityUncheckedLocked(ActivityStackSupervisor.java:1769)
    at com.android.server.am.ActivityStackSupervisor.startActivityLocked(ActivityStackSupervisor.java:1249)
    at com.android.server.am.ActivityStackSupervisor.startActivityMayWait(ActivityStackSupervisor.java:741)
    at com.android.server.am.ActivityManagerService.startActivityAsUser(ActivityManagerService.java:3118)
    at com.android.server.am.ActivityManagerService.startActivity(ActivityManagerService.java:3104)
    at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:135)
    at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2071)
    at android.os.Binder.execTransact(Binder.java:404)
    at dalvik.system.NativeStart.run(Native Method)
 Caused by: java.lang.ClassNotFoundException: com.pack1.pack2.pack3.helpers.RootNavigationOption
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:251)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:2262)
    at java.io.ObjectInputStream.readEnumDescInternal(ObjectInputStream.java:1553)
    at java.io.ObjectInputStream.readEnumDesc(ObjectInputStream.java:1534)
    at java.io.ObjectInputStream.readEnum(ObjectInputStream.java:1579)
    at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:768)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1981)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1938)
    at android.os.Parcel.readSerializable(Parcel.java:2213)
    ... 16 more
 Caused by: java.lang.NoClassDefFoundError: com/pack1/pack2/pack3/helpers/RootNavigationOption
    ... 26 more
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.pack1.pack2.pack3.helpers.RootNavigationOption" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
    ... 26 more
我已更改应用程序的逻辑,使其不在
包中仅使用此枚举值,例如作为方法参数,现在它运行时没有任何异常。有人知道为什么会这样吗


我现在也对这个问题表示感谢,因为我更加困惑。

正如我在评论中所建议的(假设Constants.VIEW_模式是字符串键):

编辑:

嗯……所以公共构造函数没有按照文档进行工作令人震惊。 也许我们可以使用另一种方法强制进行更改:

试试这个,让我知道会发生什么:

 Bundle activityOptions = new Bundle(); 
 activityOptions.setClassLoader(RootNavigationOption.class.getClassLoader());
 activityOptions.putSerializable(Constants.VIEW_MODE, RootNavigationOption.HOME);

我相信问题在于Android使用多类加载器

您可以尝试在
getSerializable()之前设置类加载器


实际上,我建议不要使用serializable,而是实现您自己的parcellable。

看起来Android正在另一个进程上拆分,该进程的意图被传递并试图处理,而您的枚举不存在;阅读:了解更多信息

只需使用
enum.ordinal()
将enum ordinal用作额外的;此外,这将使您的
RootNavigationOption.getValuePosition()
过时

例如:

final Intent=new Intent(这个,MainActivity.class);
intent.putExtra(Constants.VIEW_模式,RootNavigationOption.SETTINGS.ordinal());
稍后在您的主要活动(或类似活动)中:

final int defaultViewModeOrdinal=RootNavigationOption.HOME.ordinal();
final int viewModeOrdinal=getIntent().getIntExtra(Constants.VIEW_MODE,defaultViewModeOrdinal);
final RootNavigationOption viewMode=RootNavigationOption.values()[viewModeOrdinal];

虽然序数方法有效,但我建议更明确地说明这些值。这确实增加了一些代码来实现,但是它使代码更加可读和明确,以防止可能出现的问题,如重新排序或在列表中间插入新值。
public enum RootNavigationOption {
    HOME(0, R.string.home, R.drawable.ic_home),
    SETTINGS(1, R.string.settings, R.drawable.ic_settings),
    LOGOUT(2, R.string.logout_label, R.drawable.ic_logout);

    // Note the added code instance variable here, used in the constructor as well.
    private final int code;
    private final int navigationOptionLabelResId;
    private final int navigationOptionImageResId;

    private RootNavigationOption(int code,
                                 int navigationOptionLabelResId,
                                 int navigationOptionImageResId) {
        this.code = code;
        this.navigationOptionLabelResId = navigationOptionLabelResId;
        this.navigationOptionImageResId = navigationOptionImageResId;
    }

    public int getNavigationOptionLabelResId() {
        return navigationOptionLabelResId;
    }

    public int getNavigationOptionImageResId() {
        return navigationOptionImageResId;
    }

    public int getCode() {
        return code;
    }

    public static RootNavigationOption fromCode(int code) {
        switch(code) {
            case 0:
                return HOME;
            case 1:
                return SETTINGS;
            case 2:
                return LOGOUT;
            default:
                throw new RuntimeException(
                    "Illegal RootNavigationOption: " + code);
        }
    }
}
然后可以这样使用:

// Put
Bundle bundle = new Bundle();
bundle.putInt("key", RootNavigationOption.HOME.getCode());

// Get 
RootNavigationOption rootNavigationOption = RootNavigationOption.fromCode(bundle.getInt("key"));

在路径上:DexPathList[[directory]”,nativeLibraryDirectories=[/system/lib]]
但是你说你的类存储在
bin
文件夹中?这是特别的,根据Enum的文档,它说它是可序列化的@JoxTraex不仅如此——我成功地在一个Bundle中使用了另一个enum(但它是一个片段的参数)。嗯,大小有差异吗?这可能与此有关吗?@BNK我使用ADT进行开发,是的,这些类位于项目的bin文件夹中。不过,我可能在评论的路径部分遗漏了您所指的内容。谢谢您的建议,但这个问题对我来说仍然存在。@BorisStrandjev看到我编辑的答案,我拒绝就此放弃:)仍然是相同的结果,肯定是类加载器问题,但我已经达到了极限。我的最后一次尝试,以更Java的方式强制类加载器:
activityOptions.setClassLoader(Thread.currentThread().getContextClassLoader())谢谢你的链接。你能推测另一个分解的过程吗?你是从包含导致问题的捆绑包的意图开始的吗?我是在同一个过程中启动一个活动?什么样的活动——我想说的是:你能想到Android会为任何正在启动的活动启动一个单独的进程,而这个意图是通过这些活动传递的吗?launcher活动会启动这一行中的第二个活动。我认为没有理由进行特殊处理
bundle.setClassLoader(getClass().getClassLoader());
public enum RootNavigationOption {
    HOME(0, R.string.home, R.drawable.ic_home),
    SETTINGS(1, R.string.settings, R.drawable.ic_settings),
    LOGOUT(2, R.string.logout_label, R.drawable.ic_logout);

    // Note the added code instance variable here, used in the constructor as well.
    private final int code;
    private final int navigationOptionLabelResId;
    private final int navigationOptionImageResId;

    private RootNavigationOption(int code,
                                 int navigationOptionLabelResId,
                                 int navigationOptionImageResId) {
        this.code = code;
        this.navigationOptionLabelResId = navigationOptionLabelResId;
        this.navigationOptionImageResId = navigationOptionImageResId;
    }

    public int getNavigationOptionLabelResId() {
        return navigationOptionLabelResId;
    }

    public int getNavigationOptionImageResId() {
        return navigationOptionImageResId;
    }

    public int getCode() {
        return code;
    }

    public static RootNavigationOption fromCode(int code) {
        switch(code) {
            case 0:
                return HOME;
            case 1:
                return SETTINGS;
            case 2:
                return LOGOUT;
            default:
                throw new RuntimeException(
                    "Illegal RootNavigationOption: " + code);
        }
    }
}
// Put
Bundle bundle = new Bundle();
bundle.putInt("key", RootNavigationOption.HOME.getCode());

// Get 
RootNavigationOption rootNavigationOption = RootNavigationOption.fromCode(bundle.getInt("key"));