2011-01-31 2 views
24

Я совершенно не новичок, чтобы размещать вопросы здесь, однако я много читал здесь много лет. Обычно я всегда могу найти ответы, тщательно просматривая веб-страницы, но на этот раз я затрудняюсь ...Android: Parcelable.writeToParcel и Parcelable.Creator.createFromParcel никогда не называются

После того, как мы провели еще один день, пытаясь понять, почему это не работает, я решил спросить за помощь, надеясь, что вы, ребята, можете дать мне несколько указателей или, лучше, решение.

Проблема: В игре для Android я пришел к тому моменту, когда я должен заставить приложение запомнить его состояние, когда пользователь, например. нажимает кнопку HOME. После некоторых поисков я понял, что для того, чтобы мои классы инициализировались обратно в соответствующие состояния после повторного открытия приложения, мне пришлось поддерживать интерфейс Parcelable, чтобы передать их с помощью Bundle.

В моих функциях onStop и onStart я соответственно сохраняю и восстанавливаю состояние игры в и из Bundle, однако, когда я вызываю функции putParcelable и getParcelable на Bundle, функции writeToParcel объекта и функции createFromParcel никогда не вызываются.

Опасаясь, что это связано с относительной сложностью игры, я подумал, что лучше всего создать очень простое приложение, чтобы попытаться заставить его работать.

На основе многих Parcelable примеров, которые я видел в Интернете, это стало моим классом:

public class ParcelableTest implements Parcelable { 
    int id; 

    public ParcelableTest(int newID) 
    { 
    id = newID; 
    } 

    private ParcelableTest(Parcel in) { 
     readFromParcel(in); 
    } 

    public void writeToParcel(Parcel out, int arg1) { 
     writeToParcel(out); 
    } 

    public void writeToParcel(Parcel out) { 
    Log.v("ParcelableTest","Writing to parcel"); 
     out.writeInt(id); 
    } 

    public void readFromParcel(Parcel in) { 
     id = in.readInt(); 
    } 

    public int describeContents() { 
     return 0; 
    } 

    public static final Parcelable.Creator<ParcelableTest> CREATOR = new 
    Parcelable.Creator<ParcelableTest>() { 
     public ParcelableTest createFromParcel(Parcel in) { 
      Log.v("ParcelableTest","Creating from parcel"); 
       return new ParcelableTest(in); 
     } 

     public ParcelableTest[] newArray(int size) { 
       return new ParcelableTest[size]; 
     } 
    }; 
} 

И от моей основной деятельности я бы назвал следующие функции для сохранения/восстановления данных:

public Bundle saveToBundle(Bundle savedState) 
    { 
     savedState.putParcelable("Test1",mTest1); 
     savedState.putParcelable("Test2",mTest2); 
     return savedState; 
    } 
    public void restoreFromBundle(Bundle savedState) 
    { 
     mTest1 = savedState.getParcelable("Test1"); 
     mTest2 = savedState.getParcelable("Test2"); 

    } 

Но по какой-то причине ни одна из функций (с функциями putParcelable и getParcelable) не приведет к соответствующим Parcelable вызовам в моем тестовом классе.

Самое странное, что он как-то читает правильные значения (я пробовал с большим количеством переменных в классе), но моя отладка и мой журнал показывают, что приложение никогда не получает writeToParcel и createFromParcel.

Что мне здесь не хватает?

Любая помощь/мысли будут оценены.

+0

Если ответ решит ваш вопрос, вы бы отметили это? Или вы нашли лучшее решение своей проблемы? Не могли бы вы разместить это здесь? – superjos

ответ

10

Очевидно, что класс Android Bundle не придерживается догоняющего протокола, который вместо этого следует во время сортировки IPC.

Вместо этого кажется, что реализация Bundle просто записывает и читает объект Parcelable в свою собственную внутреннюю карту с помощью отражения. Из теста, который мы сделали, кажется, что Bundle пишет/читает каждое поле, определенное в вашем производном от Parcelable, только потому, что вы объявили эти поля.

+2

Кажется, что это верно, за исключением случаев, когда действие уничтожается, когда вызываются возможные методы. – newfivefour

+0

То же самое здесь. Не поможет даже обозначение переменной как переходного. Он по-прежнему будет сериализован. Это неожиданное поведение, представляющее неприятные ошибки. Кто-нибудь из вас открыл галочку по этому поводу? – MaiOM

+0

Нет, мы этого не сделали. Оглядываясь назад, вероятно, мы думали, что это что-то слишком близко к деталям реализации, а не к цели, которой должен служить Bundle. В основном я согласен с тем, что написал @Luis. – superjos

4

Технически документация не говорит о том, что writeToParcel или createFromParcel вызывают от onSaveInstance. На самом деле, если вы проверите savedState в своем коде, вы обнаружите, что это точно такой же экземпляр объекта как в случае сохранения, так и в случае восстановления; имеет смысл избегать сериализации-десериализации, если можно.
OTOH, в документации не говорится, что сериализация не выполняется. Вывод должен заключаться в том, что вы не должны зависеть ни от одного из них, просто предположите, что вы получаете правильный комплект.

Кроме того, вы можете проверить http://developer.android.com/guide/topics/resources/runtime-changes.html

0

Я подтверждаю, что сказал superjos. В событии saveToBundle Android-пакет просто хранит члены класса за отражение и не вызывает функции Parcelable. Я потерял один день на эту проблему! sad ....

Это действительно плохо .... Это означает, что вы потенциально храните огромное количество данных для ничего, используя этот способ.

Смежные вопросы