У меня есть класс, который реализует Parcelable
.
Я сохраняю этот объект в пакете действий onSaveInstanceState
и пытаюсь воссоздать объект в onCreate
. Это выглядит следующим образом:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
// this line does NOT call my constructor, why not?
// AND I don't get the same object as before => I get an uninitialised object
mStackManager = savedInstanceState.getParcelable(BackstackManager.TAG);
// the list and map in the object are NULL after this...
}
else
{
mStackManager = new BackstackManager();
...
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelable(BackstackManager.TAG, mStackManager);
}
Когда класс Parcelable создан, он должен вызвать конструктор класса, который можно разделить, не так ли? Мой пакетный класс извлекается из пакета, но он не похож на сохраненный объект, он даже не инициализирован...
Мой упрощенный разделяемый класс выглядит следующим образом:
public class BackstackManager implements Parcelable
{
public static final String TAG = BackstackManager.class.getName();
private List<List<Pair<Class<?>, Pair<Integer, String>>>> mBackstack;
private Map<String, Fragment.SavedState> mSavedStateMap;
public BackstackManager()
{
init();
}
private void init()
{
mBackstack = new ArrayList<List<Pair<Class<?>, Pair<Integer, String>>>>();
mSavedStateMap = new HashMap<String, Fragment.SavedState>();
}
// ----------------------
// Parcelable
// ----------------------
public static final Parcelable.Creator<BackstackManager> CREATOR =
new Parcelable.Creator<BackstackManager>()
{
@Override
public BackstackManager createFromParcel(Parcel source)
{
return new BackstackManager(source);
}
@Override
public BackstackManager[] newArray(int size)
{
return new BackstackManager[size];
}
};
public BackstackManager(Parcel source)
{
init();
readFromParcel(source);
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(mBackstack.size());
for (int i = 0; i < mBackstack.size(); i++)
{
List<Pair<Class<?>, Pair<Integer, String>>> data = mBackstack.get(i);
dest.writeInt(data.size());
for (int j = 0; j < data.size(); j++)
{
Class<?> clazz = data.get(j).first;
Integer id = data.get(j).second.first;
String tag = data.get(j).second.second;
Fragment f = mFragmentManager.findFragmentByTag(tag);
// 1) save backstack data
ParcelBundleUtils.writeStringNullSafe(dest, clazz != null ? clazz.getName() : null);
dest.writeInt(id);
dest.writeString(tag);
// 2) save fragment state, if possible
ParcelBundleUtils.writeBoolean(dest, f != null);
if (f != null)
ParcelBundleUtils.writeParcelableNullSafe(dest, mFragmentManager.saveFragmentInstanceState(f), 0);
}
}
}
public void readFromParcel(Parcel source)
{
int backstackSize = source.readInt();
for (int i = 0; i < backstackSize; i++)
{
ArrayList<Pair<Class<?>, Pair<Integer, String>>> data = new ArrayList<Pair<Class<?>, Pair<Integer, String>>>();
int dataSize = source.readInt();
for (int j = 0; j < dataSize; j++)
{
// 1) read backstack data
String clazzName = ParcelBundleUtils.readStringNullSafe(source);
Class<?> clazz = null;
if (clazzName != null)
{
try
{
clazz = Class.forName(clazzName);
}
catch (ClassNotFoundException e)
{
L.e(this, e);
}
}
Integer id = source.readInt();
String tag = source.readString();
// 2) read fragment state if possible
boolean savedStateExists = ParcelBundleUtils.readBoolean(source);
if (savedStateExists)
{
SavedState state = ParcelBundleUtils.readParcelableNullSafe(source, SavedState.class.getClassLoader());
if (state != null)
mSavedStateMap.put(tag, state);
}
data.add(new Pair<Class<?>, Pair<Integer, String>>(clazz, new Pair<Integer, String>(id, tag)));
}
mBackstack.add(data);
}
}
}
Мой ParcelBundleUtils
просто немного пишет, если объект является нулевым или нет, и зависит от этого чтения/записи фактического объекта...
ИЗМЕНИТЬ
мой текущий обходной путь заключается в использовании функции чтения/записи для пакета, который делает ТОЧНО (я скопировал и вставил свой код и просто заменил функции чтения/записи) так же, как функция чтения/записи пакета, но записывает данные непосредственно в бандл... Но очень хотелось бы знать, почему вышеперечисленное не работает как бандероль
ИЗМЕНИТЬ 2
Я нашел следующее: Android: Parcelable.writeToParcel и Parcelable.Creator. createFromParcel никогда не вызывается
Но если это проблема, я не буду единственным, кто столкнулся с этой проблемой...
init()
должен быть вызван. Пожалуйста, разместите код вreadFromParcel()
иwriteToParcel()
- person David Wasser   schedule 04.11.2014mStackManager
на самом деле неnull
после того, как вы позвонилиgetParcelable
? - person Jeffrey Mixon   schedule 04.11.2014mStackManager
не нуль... но внутренний список и карта нулевые... Еще одна странная деталь: у меня есть слушатель, который, конечно, не сохраняется в посылке... это не нуль после вызоваgetParcelable
... Хотя следовало бы, конечно... - person prom85   schedule 04.11.2014onDestroy
почистил свой объект (я думал, что объект все равно сохраняется в бандле и потом будет пересоздан)... Это было неправильно, я просто должен отказаться от своих ссылок, не более того . Потому что пакет будет упаковывать мой объект только в случае необходимости, НЕ ВСЕГДА... Он не упаковывает его, например, при повороте экрана... - person prom85   schedule 06.11.2014