Создание Parcelable из пакета не вызывает конструктор

У меня есть класс, который реализует 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 никогда не вызывается

Но если это проблема, я не буду единственным, кто столкнулся с этой проблемой...


person prom85    schedule 04.11.2014    source источник
comment
Ваш метод init() должен быть вызван. Пожалуйста, разместите код в readFromParcel() и writeToParcel()   -  person David Wasser    schedule 04.11.2014
comment
отладка показывает, что он не вызывается... ни один из конструкторов... и я добавил код функциональности чтения и записи   -  person prom85    schedule 04.11.2014
comment
Вы хотите сказать, что mStackManager на самом деле не null после того, как вы позвонили getParcelable?   -  person Jeffrey Mixon    schedule 04.11.2014
comment
Звучит очень странно. Я просмотрел этот вопрос и ваш код уже дюжину раз и не вижу в этом ничего плохого. Ваше объяснение лишено логического смысла.   -  person David Wasser    schedule 04.11.2014
comment
Точно... mStackManager не нуль... но внутренний список и карта нулевые... Еще одна странная деталь: у меня есть слушатель, который, конечно, не сохраняется в посылке... это не нуль после вызова getParcelable ... Хотя следовало бы, конечно...   -  person prom85    schedule 04.11.2014
comment
то, что я нашел, следующее: createfromparcel являются ne">stackoverflow.com/questions/4853952/. Может с этим связано...   -  person prom85    schedule 04.11.2014
comment
О, это противно :-(   -  person David Wasser    schedule 05.11.2014
comment
Я нашел проблему... Я своими действиями onDestroy почистил свой объект (я думал, что объект все равно сохраняется в бандле и потом будет пересоздан)... Это было неправильно, я просто должен отказаться от своих ссылок, не более того . Потому что пакет будет упаковывать мой объект только в случае необходимости, НЕ ВСЕГДА... Он не упаковывает его, например, при повороте экрана...   -  person prom85    schedule 06.11.2014


Ответы (1)


Вы должны указать следующую строку в качестве первой строки в переопределении onCreate(Bundle):

 super.onCreate(savedInstanceState);

Вот почему ваше состояние работает неправильно.

person Jeffrey Mixon    schedule 04.11.2014
comment
На самом деле, я использую действие... Вы правы, это будет проблемой, но это также приведет к сбою моего обходного пути... Я забыл добавить вызов super.onCreate(savedInstanceState), потому что я использую некоторый BaseActivity, который разбивает onCreate в onBeforeCreate и onAfterCreate, поэтому мой базовый класс всегда вызывает super.onCreate(savedInstanceState)... - person prom85; 04.11.2014