【问题标题】:Parcelable creation from a bundle does not call constructor从包创建 Parcelable 不会调用构造函数
【发布时间】:2014-11-04 13:20:30
【问题描述】:

我有一个实现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 类时,它应该调用 Parcelable 类的构造函数,不是吗?我的 parcelable 类是从包中检索到的,但它看起来不像保存的对象,甚至没有初始化...

我的简化 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 and Parcelable.Creator.createFromParcel are never called

但如果这就是问题所在,我不会是唯一一个面临这个问题的人......

【问题讨论】:

  • 应该调用你的init() 方法。请将代码发布在readFromParcel()writeToParcel()
  • 调试显示,它没有被调用……构造函数都没有……我添加了读写功能代码
  • 你是说mStackManager在你调用getParcelable之后实际上不是null
  • 听起来很奇怪。我已经看过这个问题和你的代码十几次了,看不出有什么问题。你的解释没有逻辑意义。
  • 我发现了问题...我的活动onDestroy 我清理了我的对象(我想,对象无论如何都会保存到捆绑包中,然后会重新创建)...这是错误的,我应该放弃我的参考资料,仅此而已。因为捆绑只会包裹我的对象,如果有必要,不总是……它不会在屏幕旋转时包裹它……

标签: android android-activity bundle parcel


【解决方案1】:

必须将以下行作为onCreate(Bundle) 覆盖的第一行:

 super.onCreate(savedInstanceState);

这就是您的状态无法正常工作的原因。

【讨论】:

  • 实际上,我使用了一个活动......你是对的,这将是一个问题,但这也会使我的解决方法失败......我忘了添加 super.onCreate(savedInstanceState) 调用,因为我正在使用一些BaseActivity,它将onCreate 拆分为onBeforeCreateonAfterCreate,因此我的基类总是调用super.onCreate(savedInstanceState)...
猜你喜欢
  • 2013-09-24
  • 2016-12-01
  • 1970-01-01
  • 2021-07-17
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
相关资源
最近更新 更多