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.

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

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


person AD-Venture    schedule 31.01.2011    source источник
comment
Если бы ответ решил ваш вопрос, вы бы отметили это? Или вы нашли лучшее решение вашей проблемы? Не могли бы вы опубликовать это здесь?   -  person superjos    schedule 10.12.2012


Ответы (3)


По-видимому, класс Android Bundle не соответствует протоколу parcelable, который вместо этого используется при маршаллинге IPC.

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

person superjos    schedule 14.04.2011
comment
Это кажется верным, за исключением случаев, когда активность уничтожается, когда вызываются разделяемые методы. - person mmm111mmm; 29.10.2013
comment
То же самое. Не поможет даже пометка переменной как переходной. Он все равно будет сериализован. Это неожиданное поведение, вызывающее неприятные ошибки. Кто-нибудь из вас открывал галочку по этому поводу? - person MaiOM; 16.06.2014
comment
Нет, мы этого не сделали. Оглядываясь назад, мы, вероятно, думали, что это было что-то слишком близко к деталям реализации, а не к цели, которой должен служить Bundle. В основном я согласен с тем, что написал @Luis. - person superjos; 16.06.2014
comment
это где-нибудь задокументировано? - person dldnh; 07.09.2014
comment
В то время (3+ года назад) мы ничего не смогли найти об этом. Мы учились на горьком опыте. Кроме того, что касается документации, посмотрите ответ @Luis - person superjos; 08.09.2014
comment
@newfivefour правильно. Если вам нужно что-то отладить в ваших методах, которые можно разделить, вы можете сделать это, войдя в «Параметры разработчика» и отметив «Не сохранять действия». - person yuval; 24.05.2016

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

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

person Luis    schedule 08.07.2013

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

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

person existenz31    schedule 16.11.2013