Подтвердить что ты не робот

Unmarshalling ошибки в приложении Android с настраиваемыми классными классами

Для моего приложения для Android я получаю несколько ошибок, не связанных с сортировкой, хотя я думаю, что сделал все, что необходимо для правильного сохранения и загрузки объектов с помощью Parcelable s. Можете ли вы сказать мне, что случилось с моим кодом?

Ошибка 1:

java.lang.RuntimeException: Unable to start activity ComponentInfo
Caused by: java.lang.RuntimeException: Parcel [email protected]: Unmarshalling unknown type code 6619241 at offset 1372
at android.os.Parcel.readValue(Parcel.java:1922)
at android.os.Parcel.readMapInternal(Parcel.java:2094)
at android.os.Bundle.unparcel(Bundle.java:223)
at android.os.Bundle.getParcelable(Bundle.java:1158)
at android.app.Activity.onCreate(Activity.java:860)
at my.app.package.PlayComputer.onCreate(PlayComputer.java:1012)
at android.app.Activity.performCreate(Activity.java:4465)

Строка 1012 в MyActivity - это вызов super.onCreate(savedInstanceState); в Activity onCreate().

protected void onSaveInstanceState(Bundle savedInstanceState) {
    if (myObject == null) {
        savedInstanceState.putParcelable("myObject", null);
    }
    else {
        savedInstanceState.putParcelable("myObject", myObject);
    }
    savedInstanceState.putInt(...);
    savedInstanceState.putString(...);
    savedInstanceState.putBoolean(...);
    super.onSaveInstanceState(savedInstanceState);
}

myObject имеет класс myObject, который имеет следующие методы:

public void writeToParcel(Parcel out, int flags) {
    out.writeIntArray(...);
    out.writeInt(...);
    out.writeStringArray(...);
    out.writeString(...);
    out.writeParcelableArray(..., flags);
}

public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() {
    public MyObject createFromParcel(Parcel in) {
        try {
            if (in == null) {
                return null;
            }
            else {
                return new MyObject(in);
            }
        }
        catch (Exception e) {
            return null;
        }
    }
    public MyObject[] newArray(int size) {
        return new MyObject[size];
    }
};

private MyObject(Parcel in) {
    in.readIntArray(...);
    ... = in.readInt();
    in.readStringArray(...);
    ... = in.readString();
    ... = (OtherObject[]) in.readParcelableArray(OtherObject.class.getClassLoader());
}

Ошибка 2:

java.lang.RuntimeException: Unable to start activity ComponentInfo
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling:
at android.os.Parcel.readParcelable(Parcel.java:1971)
at android.os.Parcel.readValue(Parcel.java:1859)
at android.os.Parcel.readMapInternal(Parcel.java:2099)
at android.os.Bundle.unparcel(Bundle.java:223)
at android.os.Bundle.getParcelable(Bundle.java:1158)
at android.app.Activity.onCreate(Activity.java:905)
at my.app.package.PlayComputer.onCreate(SourceFile:1012)

Те же файлы и классы.

Ошибка 3:

java.lang.RuntimeException: Unable to start activity ComponentInfo
Caused by: java.lang.RuntimeException: Parcel [email protected]: Unmarshalling unknown type code 7340149 at offset 1276
at android.os.Parcel.readValue(Parcel.java:1913)
at android.os.Parcel.readMapInternal(Parcel.java:2083)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getParcelable(Bundle.java:1100)
at my.app.package.PlayComputer.onCreate(SourceFile:1111)

На этот раз вызывающая строка (1111) будет следующей:

myObject = (MyObject) savedInstanceState.getParcelable("myObject");
4b9b3361

Ответ 1

В Android есть два разных загрузчика классов: класс classloader (который знает, как загружать классы Android) и загрузчик классов APK (который знает, как загрузить ваш код). У загрузчика классов APK есть класс загрузчика классов, который является его родительским, то есть он также может загружать классы Android.

Ошибка # 2, скорее всего, вызвана Bundle с использованием класса classloader, поэтому он не знает ваших классов. Я думаю, что это может произойти, когда Android необходимо сохранить ваш Bundle, а затем восстановить его (например, при нехватке памяти в фоновом режиме). Вы можете исправить это, установив загрузчик классов APK в комплекте:

savedInstanceState.setClassLoader(GetClass() getClassLoader().);

Ошибка №1 и №3 более загадочна, возможно, вы пишете нулевые значения в writeToParcel()? Android не очень нравится, я боюсь.

Ответ 2

По внешнему виду, createFromParcel и newArray должны быть переопределены следующим образом:

public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() {
    @Override
    public MyObject createFromParcel(Parcel in) {
        MyObject myObj = new MyObject();
        myObj.intArray = in.readIntArray(...);
        myObj.intValue = in.readInt(...);
        // ....
        // IN THE SAME ORDER THAT IS WRITTEN OUT AS PER writeToParcel!
        //
        return myObj;
    }
    @Override
    public MyObject[] newArray(int size) {
        return new MyObject[size];
    }
};

Edit:

Я забыл упомянуть, что для того, чтобы выше работало, должен был быть пустой конструктор!

public MyObject(){}

Ответ 3

Перед чтением из набора пакетов ClassLoader

bundle.setClassLoader(GetClass() getClassLoader().);

это спасло мое время!