解组 Android Intent Parcelable 时找不到类

Posted

技术标签:

【中文标题】解组 Android Intent Parcelable 时找不到类【英文标题】:Class not found when Unmarshalling Android Intent Parcelable 【发布时间】:2014-04-23 18:41:23 【问题描述】:

我有一个 ArrayListactivities 之间传递。在这个ArrayList 中是由class 组成的对象,其中有四个变量。其中一个变量是另一个ArrayList<object>,它来自另一个class

我已经在两者上实现了 Parcelable 并且我很确定我已经正确地完成了 parcelable 方法。以下是错误:

错误:

03-18 02:37:27.063: D/dalvikvm(3249): GC_FOR_ALLOC freed 82K, 6% free 3020K/3180K, paused 1ms, total 3ms
03-18 02:37:27.093: I/dalvikvm-heap(3249): Grow heap (frag case) to 3.626MB for 635808-byte allocation
03-18 02:37:27.103: D/dalvikvm(3249): GC_FOR_ALLOC freed 5K, 5% free 3635K/3804K, paused 10ms, total 10ms
03-18 02:37:27.173: D/(3249): HostConnection::get() New Host Connection established 0xb96396c0, tid 3249
03-18 02:37:27.243: W/EGL_emulation(3249): eglSurfaceAttrib not implemented
03-18 02:37:27.253: D/OpenGLRenderer(3249): Enabling debug mode 0
03-18 02:37:27.293: W/EGL_emulation(3249): eglSurfaceAttrib not implemented
03-18 02:37:32.383: D/dalvikvm(3249): GC_FOR_ALLOC freed 238K, 8% free 3911K/4224K, paused 1ms, total 1ms
03-18 02:37:32.383: E/Parcel(3249): Class not found when unmarshalling: com.example.Choices
03-18 02:37:32.383: E/Parcel(3249): java.lang.ClassNotFoundException: com.example.Choices
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.Class.classForName(Native Method)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.Class.forName(Class.java:251)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.Class.forName(Class.java:216)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readParcelableCreator(Parcel.java:2133)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readParcelable(Parcel.java:2097)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readValue(Parcel.java:2013)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readListInternal(Parcel.java:2343)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readArrayList(Parcel.java:1703)
03-18 02:37:32.383: E/Parcel(3249):     at com.example.midterm.Question.<init>(Question.java:76)
03-18 02:37:32.383: E/Parcel(3249):     at com.example.midterm.Question$1.createFromParcel(Question.java:98)
03-18 02:37:32.383: E/Parcel(3249):     at com.example.midterm.Question$1.createFromParcel(Question.java:1)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readParcelable(Parcel.java:2104)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readValue(Parcel.java:2013)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readListInternal(Parcel.java:2343)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readArrayList(Parcel.java:1703)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readValue(Parcel.java:2034)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Bundle.unparcel(Bundle.java:249)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Bundle.getParcelableArrayList(Bundle.java:1250)
03-18 02:37:32.383: E/Parcel(3249):     at com.example.midterm.TriviaActivity.onCreate(TriviaActivity.java:20)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.Activity.performCreate(Activity.java:5231)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Handler.dispatchMessage(Handler.java:102)
03-18 02:37:32.383: E/Parcel(3249):     at android.os.Looper.loop(Looper.java:136)
03-18 02:37:32.383: E/Parcel(3249):     at android.app.ActivityThread.main(ActivityThread.java:5017)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.reflect.Method.invokeNative(Native Method)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.reflect.Method.invoke(Method.java:515)
03-18 02:37:32.383: E/Parcel(3249):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-18 02:37:32.383: E/Parcel(3249):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-18 02:37:32.383: E/Parcel(3249):     at dalvik.system.NativeStart.main(Native Method)
03-18 02:37:32.383: E/Parcel(3249): Caused by: java.lang.NoClassDefFoundError: com/example/midterm/Choices
03-18 02:37:32.383: E/Parcel(3249):     ... 34 more
03-18 02:37:32.383: E/Parcel(3249): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.midterm.Choices" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib]]
03-18 02:37:32.383: E/Parcel(3249):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
03-18 02:37:32.383: E/Parcel(3249):     at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
03-18 02:37:32.383: E/Parcel(3249):     ... 34 more
03-18 02:37:32.383: D/AndroidRuntime(3249): Shutting down VM
03-18 02:37:32.383: W/dalvikvm(3249): threadid=1: thread exiting with uncaught exception (group=0xb2cb8b20)
03-18 02:37:32.383: E/AndroidRuntime(3249): FATAL EXCEPTION: main
03-18 02:37:32.383: E/AndroidRuntime(3249): Process: com.example.midterm, PID: 3249
03-18 02:37:32.383: E/AndroidRuntime(3249): java.lang.RuntimeException: Unable to start activity ComponentInfocom.example/com.example.TriviaActivity: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.example.Choices
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Handler.dispatchMessage(Handler.java:102)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Looper.loop(Looper.java:136)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread.main(ActivityThread.java:5017)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at java.lang.reflect.Method.invokeNative(Native Method)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at java.lang.reflect.Method.invoke(Method.java:515)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at dalvik.system.NativeStart.main(Native Method)
03-18 02:37:32.383: E/AndroidRuntime(3249): Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.example.midterm.Choices
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readParcelableCreator(Parcel.java:2147)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readParcelable(Parcel.java:2097)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readValue(Parcel.java:2013)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readListInternal(Parcel.java:2343)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readArrayList(Parcel.java:1703)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.example.Question.<init>(Question.java:76)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.example.midterm.Question$1.createFromParcel(Question.java:98)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.example.midterm.Question$1.createFromParcel(Question.java:1)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readParcelable(Parcel.java:2104)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readValue(Parcel.java:2013)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readListInternal(Parcel.java:2343)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readArrayList(Parcel.java:1703)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readValue(Parcel.java:2034)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Parcel.readArrayMapInternal(Parcel.java:2314)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Bundle.unparcel(Bundle.java:249)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.os.Bundle.getParcelableArrayList(Bundle.java:1250)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at com.example.midterm.TriviaActivity.onCreate(TriviaActivity.java:20)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.Activity.performCreate(Activity.java:5231)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-18 02:37:32.383: E/AndroidRuntime(3249):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-18 02:37:32.383: E/AndroidRuntime(3249):     ... 11 more

如您所见,解组时出现的第一个错误是 Class not found

这是我的Question 类可打包代码:

/**
 * Constructs a Question from a Parcel
 * @param parcel Source Parcel
 */
public Question (Parcel parcel) 
    this.id = parcel.readString();
    this.text = parcel.readString();
    this.image = parcel.readString();
    this.choices = parcel.readArrayList(null);


@Override
public int describeContents() 
    return 0;


// Required method to write to Parcel
@Override
public void writeToParcel(Parcel dest, int flags) 
    dest.writeString(id);
    dest.writeString(text);
    dest.writeString(image);
    dest.writeList(choices);


// Method to recreate a Question from a Parcel
public static Creator<Question> CREATOR = new Creator<Question>() 

    @Override
    public Question createFromParcel(Parcel source) 
        return new Question(source);
    

    @Override
    public Question[] newArray(int size) 
        return new Question[size];
    

;

Choices,作为ArrayList 对象插入Question 的第二个类:

/**
 * Constructs a Choice from a Parcel
 * @param parcel Source Parcel
 */
public Choices (Parcel parcel) 
    this.isCorrect = parcel.readByte() != 0;
    this.choice = parcel.readString();


@Override
public int describeContents() 
    return 0;


@Override
public void writeToParcel(Parcel dest, int flags) 
    dest.writeByte((byte) (isCorrect ? 1 : 0));
    dest.writeString(choice);


// Method to recreate a Question from a Parcel
public static Creator<Choices> CREATOR = new Creator<Choices>() 

    @Override
    public Choices createFromParcel(Parcel source) 
        return new Choices(source);
    

    @Override
    public Choices[] newArray(int size) 
        return new Choices[size];
    

;

然后我使用以下代码将ArrayList&lt;Question&gt; 放入意图中:

Intent intent = new Intent(MainActivity.this, TriviaActivity.class);
intent.putParcelableArrayListExtra(QUESTION_KEY, questions);
startActivity(intent);

questions 是 ArrayList。我的代码没有错误,也不知道哪里出错了。非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

您应该尝试将this.choices = parcel.readArrayList(null); 替换为this.choices = parcel.readArrayList(Choices.class.getClassLoader());

希望对你有帮助

【讨论】:

太棒了!正是在我用Choices.class.getClassLoader() 替换 null 时,这对我来说是正确的。谢谢! 我希望这在文档中更清楚,而不是仅仅建议您输入 null【参考方案2】:

您应该设置ClassLoader。试试这个:

public Question (Parcel parcel) 
    this.id = parcel.readString();
    this.text = parcel.readString();
    this.image = parcel.readString();
    this.choices = parcel.readTypedList(Choices.class.getClassLoader());

您也可以尝试读取和写入类型列表而不是ArrayList

public Question (Parcel parcel) 
    this.id = parcel.readString();
    this.text = parcel.readString();
    this.image = parcel.readString();
    this.choices = new ArrayList<Choices>();
    parcel.readArrayList(this.choices, Choices.Creator);

【讨论】:

以上是关于解组 Android Intent Parcelable 时找不到类的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中将 XML 文件解组为 Java 对象?

使用自定义可打包类解组 Android 应用程序中的错误

Android 和 AWS Cognito - 无法使用 proguard 解组错误响应

解组时找不到类:com.google.android.gms.location.LocationResult

YouTube Android Player API 在解组时抛出“BadParcelableException ClassNotFoundException:asc”与新的 YouTube 版本

ClassNotFoundException 解组时真的不知道为啥