【问题标题】:How to fix Unmarshalling unknown type code XXX at offset YYY in Android?如何修复 Android 中偏移 YYY 处的 Unmarshalling unknown type code XXX?
【发布时间】: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 值(但正在写入它)。它搞砸了一切,应用程序崩溃了。

标签: android serialization marshalling unmarshalling parcelable


【解决方案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 后得到修复

【讨论】:

【解决方案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)
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-25
            • 2022-08-22
            • 2011-08-09
            • 2019-11-09
            相关资源
            最近更新 更多