如何修复Android中偏移YYY的Unmarshalling未知类型代码XXX?

时间:2014-02-18 05:17:20

标签: android serialization marshalling unmarshalling parcelable

由于Unmarshalling异常,我正在恢复应用程序崩溃。我检查了所有Seri​​alizables都没有参数的构造函数,甚至使用ObjectStream检查了所有可序列化(保存到文件并从文件加载)。我如何理解导致异常的parcelable偏移的实际类类型:

Parcel android.os.Parcel@42209460: Unmarshalling unknown type code
 2131165303 at offset 3748
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2080)
         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2105)
         at android.app.ActivityThread.access$600(ActivityThread.java:136)
         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
         at android.os.Handler.dispatchMessage(Handler.java:99)
         at android.os.Looper.loop(Looper.java:137)
         at android.app.ActivityThread.main(ActivityThread.java:4876)
         at java.lang.reflect.Method.invokeNative(Native Method)
         at java.lang.reflect.Method.invoke(Method.java:511)
         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:804)
         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:571)
         at com.kdgdev.xtension.core.XtensionMain.main(XtensionMain.java:91)
         at dalvik.system.NativeStart.main(Native Method)
        Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@42209460: Unmarshalling unknown type code 2131165303
 at offset 3748
         at android.os.Parcel.readValue(Parcel.java:2032)
         at android.os.Parcel.readSparseArrayInternal(Parcel.java:2255)
         at android.os.Parcel.readSparseArray(Parcel.java:1687)
         at android.os.Parcel.readValue(Parcel.java:2022)
         at android.os.Parcel.readMapInternal(Parcel.java:2226)
         at android.os.Bundle.unparcel(Bundle.java:223)
         at android.os.Bundle.getSparseParcelableArray(Bundle.java:1232)
        at com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:1690)
         at android.app.Activity.onRestoreInstanceState(Activity.java:999)
         at com.actionbarsherlock.app.SherlockFragmentActivity.onRestoreInstanceState(Unknown
 Source)
         at name.myname.android.app.ui.MainActivity.onRestoreInstanceState(Unknown
 Source)
         at android.app.Activity.performRestoreInstanceState(Activity.java:971)
         at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1130)
         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2058)
       ... 12 more

保存的数据由BundleSerializable组成,所有这些数据都很好。

我要做下一个:

try {
// unmarshalling
} catch (Throwable t) {
// look offset 
}

我如何理解Parcelable偏移的实际类型?

11 个答案:

答案 0 :(得分:34)

写入和读取parcelables有一些规则。

1-注意类型不匹配。如果你写int,不要试着读长等。

2-注意写入和读取的顺序。在阅读和写作时,对象必须处于相同的排序顺序。

这两个都可能导致“解组未知类型代码”。

答案 1 :(得分:10)

由于Proguard混淆 - 它处理了Parcelable。 解决方案:Proguard causing RuntimeException (Unmarshalling unknown type code) in Parcelable class

答案 2 :(得分:5)

如果添加了List类型,则应为:

@Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeList(this.mList);

并使用类似的类型取消它:

protected MyClass(Parcel in) {
        super(in);
        this.mList = new ArrayList<>();
        in.readList(this.mList, MyRequiredClass.class.getClassLoader());

答案 3 :(得分:4)

在我的情况下,将支持库升级到23.2.1

后修复

答案 4 :(得分:2)

这不是Proguard相关问题..但是当proguard和minify启用它时,问题始终存在。

问题是按顺序写入和读取对象...序列应该是相同的,就像读取文件一样。

你可以使用android studio plug for make class作为parcelable https://plugins.jetbrains.com/plugin/7332?pr=

答案 5 :(得分:0)

在我的情况下,它是由超过最大限制的数据大小引起的,可以放到大约1 MB的Parcel。

解决方案:优化您的Parcelable代码以尽可能减少数据(例如,不要将Serializable对象放入Parcel)

答案 6 :(得分:0)

在我的情况下,我的课程在从另一个Parcelable父级扩展时没有添加CREATOR文件。

public class Image implements Parcelable {
        protected Image(Parcel in) {
        }

        public static final Creator<Image> CREATOR = new Creator<Image>() {
            @Override
            public Image createFromParcel(Parcel in) {
                return new Image(in);
            }

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

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

        @Override
        public void writeToParcel(Parcel dest, int flags) {
        }
}

public class ImageChild extends Image {
        protected ImageChild(Parcel in) {
            super(in);
        }


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

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
        }
}

在ImageChild中缺少CREATOR字段

答案 7 :(得分:0)

使用Kotlin,对象'Nota'有一个Custom对象'CentroCusto',它只包含原始属性。

class Nota(var id: Int? = null, var centroCusto: ArrayList<CentroCusto>? = null) : Parcelable {

constructor(source: Parcel) : this(
        source.readValue(Int::class.java.classLoader) as Int?,
        //Exception in below line -> Unmarshalling unknown type code 
        source.createTypedArrayList(CentroCusto.CREATOR) 
)

override fun describeContents() = 0

override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
    writeValue(id)
    writeTypedList(centroCusto)
}

companion object {
    @JvmField
    val CREATOR: Parcelable.Creator<Nota> = object : Parcelable.Creator<Nota> {
        override fun createFromParcel(source: Parcel): Nota = Nota(source)
        override fun newArray(size: Int): Array<Nota?> = arrayOfNulls(size)
    }
}

CentroCusto课程:

class CentroCusto(var id: Int? = null, var descricao: String? = null, var aprovacaoDiretoria: Int? = null, var permiteMarcar: Boolean? = null) : Parcelable {

constructor(parcel: Parcel) : this(
        parcel.readValue(Int::class.java.classLoader) as? Int,
        parcel.readString(),
        parcel.readValue(Int::class.java.classLoader) as? Int,
        parcel.readValue(Boolean::class.java.classLoader) as? Boolean) {
}

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeValue(id)
    parcel.writeString(descricao)
    parcel.writeValue(aprovacaoDiretoria)
    parcel.writeValue(permiteMarcar)
}

override fun describeContents(): Int {
    return 0
}

companion object CREATOR : Parcelable.Creator<CentroCusto> {
    override fun createFromParcel(parcel: Parcel): CentroCusto {
        return CentroCusto(parcel)
    }

    override fun newArray(size: Int): Array<CentroCusto?> {
        return arrayOfNulls(size)
    }
}

}

答案 8 :(得分:0)

只需删除所有可拆分方法,然后以有效顺序再次生成它们

答案 9 :(得分:0)

只需添加:使用自定义视图并且没有通过onSaveInstanceState()onRestoreInstanceState()正确保存/恢复其状态时,也会发生此错误。

因此,如果发生此错误,还请检查您的自定义视图。

答案 10 :(得分:0)

父模型具有可拆分性,子模型具有可拆分性,然后在下面的代码中使用,效果很好并且不会出现解组错误

父级模型

data class ParentModel(
    @SerializedName("post_id") val post_id: String? = "",
    @SerializedName("images") val images: ArrayList<ChildModel>? = null
) : Parcelable {
   constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.createTypedArrayList(ChildModel.CREATOR)!!
   )

   override fun writeToParcel(parcel: Parcel, flags: Int) {
       parcel.writeString(post_id)
       parcel.writeTypedList(images)
   }

   override fun describeContents(): Int {
       return 0
   }

   companion object CREATOR : Parcelable.Creator<ParentModel> {
       override fun createFromParcel(parcel: Parcel): ParentModel{
           return ParentModel(parcel)
       }

       override fun newArray(size: Int): Array<ParentModel?> {
           return arrayOfNulls(size)
       }
   }
}

子模型

data class ChildModel(
    @SerializedName("image_id") val image_id: String? = "",
    @SerializedName("image_url") val image_url: String? = ""
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(image_id)
        parcel.writeString(image_url)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<ChildModel> {
        override fun createFromParcel(parcel: Parcel): ChildModel{
            return ChildModel(parcel)
        }

        override fun newArray(size: Int): Array<ChildModel?> {
            return arrayOfNulls(size)
        }
    }
}