2016-01-15 5 views
3

Я хотел сохранить сложный объект Java во время поворота экрана, так что я сделал объект Parcelable и реализованы необходимые методы:Как работает Parcelable?

  1. в writeToParcel (Parcel Dest, Int флаги) метод, я несколько сохраненных значений «Цел».
  2. в методе Parcelable.Creator's createFromParcel (Parcel source), я получил значения из «источника» в правильном порядке и вернул соответствующий объект.

Тогда в onSaveInstanceState осколком я спас Parcelable:

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putParcelable("myObject", myObject); 
} 

и получил свой объект в OnCreate фрагмента:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    MyObject myObject = savedInstanceState.getParcelable("myObject"); 
} 

Это работало отлично.

Тогда я сделал тест:

  1. Deleted весь мой код в методе writeToParcel.
  2. Возврат null в методе createFramParcel.

Когда я запустил приложение, у меня появился ТОЧНЫЙ РЕЗУЛЬТАТ! Я получил объект со всеми соответствующими значениями в нем.

Почему это сработало? Производит ли Parcelable «Parcelable objects» автоматически?

+0

Я уверен, что порядок вызовов в 'onSaveInstanceState()' неправильный путь (вы изменяете пакет после его сохранения). – dhke

ответ

6

Да, это связано с тем, что Bundle обрабатывает кеширование и рассылку внутри. При вызове putParcelable(), он работает следующий код:

public void putParcelable(@Nullable String key, @Nullable Parcelable value) { 
    unparcel(); 
    mMap.put(key, value); 
    mFdsKnown = false; 
} 

Так в основном, данные в Bundle не сразу записываются в Parcel - mMap является ArrayMap<String, Object> и содержит кэш всех объектов в Bundle поскольку они вставлены или удалены.

В какой-то момент, writeToParcel() будет называться на Bundle, в котором указать все в mMap будет записано в mParcelledData.

Так в основном, когда вы делаете изменения конфигурации, то Bundle до сих пор не было написано в Parcel, так и тот же экземпляр объекта, переданному в еще хранится в Bundle «s mMap (так что ваш объект также никогда не было вызвано writeToParcel() - вы можете подтвердить это, утверждая, что объект до и после изменения конфигурации имеет то же самое System.identityHashCode()).

Вы можете увидеть заметки об этом в BaseBundle:

// Invariant - exactly one of mMap/mParcelledData will be null 
// (except inside a call to unparcel) 

ArrayMap<String, Object> mMap = null; 

/* 
* If mParcelledData is non-null, then mMap will be null and the 
* data are stored as a Parcel containing a Bundle. When the data 
* are unparcelled, mParcelledData willbe set to null. 
*/ 
Parcel mParcelledData = null; 

Так что, если вы должны были написать свой Parcelable объект в сохранении состояния пучка, и поместить приложение в фоновом режиме, пока процесс не умирает (или я полагаю, вы можете заставить это, запустив adb shell am kill <application_id>), а затем возобновите работу, вы столкнетесь с проблемой, когда ваши данные не будут правильно распределены.

+1

Большое вам спасибо за разъяснение! –

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

  • Нет связанных вопросов^_^