如何修复 Android 中偏移 YYY 处的 Unmarshalling unknown type code XXX?

Posted

技术标签:

【中文标题】如何修复 Android 中偏移 YYY 处的 Unmarshalling unknown type code XXX?【英文标题】:How to fix Unmarshalling unknown type code XXX at offset YYY in Android? 【发布时间】:2014-03-17 16:27:07 【问题描述】:

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

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

保存的数据由Bundles 和Serializables 组成,它们看起来都不错。

我会做下一个:

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

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

【问题讨论】:

这发生在我身上,因为我没有从我的 Parcel 中读取一个 int 值(但正在写入它)。它搞砸了一切,应用程序崩溃了。 【参考方案1】:

有一些读写parcelables的规则。

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

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

这两种情况都可能导致“Unmarshalling unknown type code”。

【讨论】:

这是我的解决方案:注意写入和读取的顺序。对象在读写时必须处于相同的排序顺序。 3 - 如果有 Parcelable 类型的字段,请注意写入和读取的顺序。 Parcelable 类型的字段在读写时必须保持相同的排序顺序。 因为异常可能发生在堆栈跟踪显示不完全的地方。例如:堆栈跟踪显示字段 A 导致异常,但实际上是 parcelable 类型的字段 B 导致异常。 由于这个答案有这么多投票,我将分享我的救命稻草超过 5 年。 parcelabler.com。肯定还有其他网站,但我正在使用这个。【参考方案2】:

这是因为 Proguard 混淆 - 它处理 Parcelable。 解决方案:Proguard causing RuntimeException (Unmarshalling unknown type code) in Parcelable class

【讨论】:

同样的问题,但它在调试时发生,所以这不是我的解决方案 - 另一个想法? @Srneczek 你找到解决方案了吗?是否也仅在 6.x 或其他版本上发生过? @ab.helly 不,我不记得是什么问题 - 如果我再次遇到这个问题,我可以回答你,但我想我使用了另一种方法来避免解组问题 对于它的价值,它也可能是你的实现。我最近在编写的自定义 ViewGroup 中遇到了这个问题。我没有使 CREATOR 成为静态的,所以当 Activity 被销毁时它会在旋转时抛出这个错误。通过在开发者选项中打开“不保留活动”很容易复制。 @worked 这可能是由于对 Parcel 的一些读取/写入。就我而言,我正在给 Parcel 写信,但没有从中读取。恢复实例状态时会导致混乱。【参考方案3】:

如果添加了一个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());

【讨论】:

如果在将 List 添加到实现 Parcelable 的类中后出现此错误,那么这就是为我解决的问题。【参考方案4】:

在我的情况下,它在将支持库升级到 23.2.1 后得到修复

【讨论】:

我想知道是什么问题,因为我在developer.android.com/topic/libraries/support-library/…没有看到任何相关问题【参考方案5】:

这不是 Proguard 相关的问题。但是当 proguard 和 minify 启用时,它的问题总是发生。

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

您可以使用 android studio 插件将 class 设为 parcelable https://plugins.jetbrains.com/plugin/7332?pr=

【讨论】:

我浪费了几个小时来解决这个问题。我遇到了同样的问题,你的建议救了我读写顺序应该是一样的【参考方案6】:

在我的情况下,我的班级在从另一个 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】:

只需删除所有可打包的方法并使用有效序列再次生成它们

【讨论】:

【参考方案8】:

使用 Kotlin,对象“Nota”有一个只包含原始属性的自定义对象“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)
    



【讨论】:

【参考方案9】:

在我的情况下,这是由于数据大小超过了可以放入 Parcel 的最大限制(大约 1 MB)引起的。

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

【讨论】:

【参考方案10】:

补充一点:当使用自定义视图并且未通过onSaveInstanceState()onRestoreInstanceState() 正确保存/恢复其状态时,也会发生此错误。

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

【讨论】:

对我来说,这是关于自定义视图之一中 CREATOR 字段的错误声明。【参考方案11】:

父模型有parcelable,子模型有parcelable,然后使用下面的代码可以正常工作并且不会出现解组错误

父模型

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)
        
    

【讨论】:

以上是关于如何修复 Android 中偏移 YYY 处的 Unmarshalling unknown type code XXX?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHP 中修复警告非法字符串偏移

如何修复php非法偏移错误[重复]

如何修复:JSON.parse (<anonymous>) 位置 0 处的 JSON 中的意外标记 <

触摸 UISearchbar 时如何修复偏移键盘

如何修复错误:不能将字符串偏移量用作数组

当我尝试使用 Laravel 中的“别名”从数据库中获取值时如何修复“未定义的偏移量:0”