【问题标题】:Android fragment not saving stateAndroid片段不保存状态
【发布时间】:2012-09-16 17:23:54
【问题描述】:

我最近将我的应用从基于活动的应用转换为基于片段的应用。这是一个记分应用程序,当它是一项活动时,我可以轻松地保存和恢复分数。但是,这似乎不能作为一个片段工作。这是我的代码:

 @Override
public void onSaveInstanceState(Bundle savedInstanceState){
    super.onSaveInstanceState(savedInstanceState);

    if(t!=null&&flag==1){
        savedInstanceState.putInt("time", t.getTimeLeft());
    } else {
        savedInstanceState.putInt("time", 0);
    }

    savedInstanceState.putIntArray("score_array", points);
    savedInstanceState.putIntArray("position_array", spinnerPosition);
    savedInstanceState.putBooleanArray("checked_array", shouldBeChecked);

    flag = 0;
    Log.d("MyApp", "savingState");
}

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);

    Log.d("MyApp", "onActivityCreated");

    try {
        int timeLeft = savedInstanceState.getInt("time");

        points = savedInstanceState.getIntArray("score_array").clone();
        spinnerPosition = savedInstanceState.getIntArray("position_array").clone();
        shouldBeChecked = savedInstanceState.getBooleanArray("checked_array").clone();

        ((BaseAdapter) ((ListView)getView().findViewById(R.id.missionList)).getAdapter()).notifyDataSetChanged();

        if(timeLeft!=0){
            flag=1;

            this.getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

            t = new TimerClass(timeLeft*1000, 1000);
            t.setViews((TextView)getView().findViewById(R.id.minuteView), (TextView)getView().findViewById(R.id.tenSecondView), (TextView)getView().findViewById(R.id.secondView), (Button)getView().findViewById(R.id.start_button));
            ((Button)getView().findViewById(R.id.start_button)).setText(R.string.stop);
            t.start();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 

}

我在onRestoreInstanceState 而不是onActivityCreated 的活动中成功使用了完全相同的代码,并且没有使用try/catch。问题是当我尝试从包中提取某些内容时,我遇到了空指针错误。我可以在日志中看到保存状态,然后是 onActivityCreated,但 onActivityCreated 似乎没有得到 onSavedInstanceState 放入包中的内容。我只是在调用savedInstanceState.getAnything() 的每一行上得到一个空指针。但是,根据我的阅读,onCreateonCreateViewonActivityCreated 都使用相同的捆绑包。我尝试将代码移到其他两个,但没有成功。

【问题讨论】:

  • 你确定在 onSaveState 方法中你没有在包中保存空值吗?
  • 非常确定。它们被初始化为非空,我没有看到任何让它们变为空的方法。它作为一项活动逐行工作。
  • 刚查过,绝对不为空。
  • 从给定的代码很难说。作为片段的 onCreate 方法中的替代方法,您可以调用方法“setRetainInstance(true)”,它将在方向更改时保留数据。你只需要确保你没有挂在任何以前的活动引用以避免内存泄漏。
  • 今天下午有机会我会这样做。您能否进一步解释以前的活动参考是什么意思?您是在谈论创建此片段的多个实例,而 setRetainInstance() 将保留所有这些实例吗?我已经确保我只创建一次片段,并在每次显示在屏幕上时打开同一个片段。另外,您说很难从给定的代码中分辨出来。还有哪些其他代码可能会有所帮助。我发布这个是因为它是与保存/恢复状态有关的所有代码。如果还有其他有用的东西,我会尝试发布它。

标签: android android-fragments savestate


【解决方案1】:

对于任何需要更好答案的人:

始终在访问 if(savedInstanceState!=null) 之前对其进行测试,以避免出现空指针错误。 另外,请注意,当您的片段被销毁时,onSaveInstanceState() 将无法在所有情况下保存您的数据。

特别是如果您的 Fragment 被推入后堆栈,并且设备被旋转。在这种情况下,只有 onDestoryView() 会在您的 Fragment 被推送到后台堆栈时被调用,因此当 onSaveInstanceState() 在设备旋转期间运行时,它将无法保存视图中的任何数据,因为它们之前都已被销毁。

有关解决方法,请参阅以下主题。我认为它对使用 Fragments 进行开发的每个人都很有用。 特别是 DroidT 的回答: https://stackoverflow.com/a/19744402/2517350

【讨论】:

    【解决方案2】:

    我最终想出了一个相当老套的解决方法。对此并不感到兴奋,因为它实际上并没有解决核心问题。如果有人能帮我找到这个,我很乐意接受这个答案。

    也就是说,我只是简单地使用了 Activity 的 onSaveInstanceState 和 onRestoreInstanceState 来保存和恢复片段数据。

    【讨论】:

    • 我认为您可能每次都在重新创建片段,请输入您如何将此片段附加到活动的代码。如果重新创建活动,如果在某些设备上通过代码添加,它将丢失之前的片段。我有同样该死的问题。最终调用 setContentView(myxml) 并且 myxml 中有片段类
    猜你喜欢
    • 2013-04-04
    • 2014-04-25
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多