当前位置: 首页 > 面试题库 >

如何正确将片段的实例状态保存在后堆栈中?

丘友樵
2023-03-14
问题内容

我在SO上发现了许多类似问题的实例,但不幸的是,没有答案符合我的要求。

我对人像和风景有不同的布局,并且我使用的是后向堆栈,这既妨碍了我的使用,又使我无法setRetainState()使用配置更改例程。

我在TextViews中向用户显示某些信息,这些信息不会保存在默认处理程序中。当仅使用“活动”编写我的应用程序时,以下方法运行良好:

TextView vstup;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.whatever);
    vstup = (TextView)findViewById(R.id.whatever);
    /* (...) */
}

@Override
public void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putCharSequence(App.VSTUP, vstup.getText());
}

@Override
public void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);
    vstup.setText(state.getCharSequence(App.VSTUP));
}

使用Fragments,这仅在非常特殊的情况下有效。具体地说,令人震惊的是替换片段,将其放回堆栈中,然后在显示新片段时旋转屏幕。据我了解,旧片段onSaveInstanceState()在被替换时不会收到调用,而是以某种方式保持链接,Activity并且当该方法View不再存在时将调用此方法,因此将我TextView的任何结果都查找到中NullPointerException

另外,我发现即使TextViews使用Fragments也可以,但Activitys保持引用不是一个好主意。在那种情况下,onSaveInstanceState()实际上可以保存状态,但是如果在隐藏片段时旋转屏幕两次,问题就会再次出现,因为onCreateView()在新实例中不会调用该片段。

我想到了将状态保存onDestroyView()到某种Bundle-type类成员元素中(实际上是更多数据,而不仅仅是一个TextView),并将其保存到其中,onSaveInstanceState()但是还有其他缺点。首先,如果该片段是当前显示,调用两个函数的顺序是相反的,所以我需要考虑两种不同的情况。必须有一个更清洁,正确的解决方案!


问题答案:

要正确保存实例状态,Fragment请执行以下操作:

1.在片段中,通过覆盖保存实例状态onSaveInstanceState()并在中还原onActivityCreated()

class MyFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's state here
        }
    }
    ...
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        //Save the fragment's state here
    }

}

2.而且很重要的一点,在活动中,你必须保存片段的实例在onSaveInstanceState()和恢复onCreate()

class MyActivity extends Activity {

    private MyFragment 

    public void onCreate(Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's instance
            mMyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "myFragmentName");
            ...
        }
        ...
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        //Save the fragment's instance
        getSupportFragmentManager().putFragment(outState, "myFragmentName", mMyFragment);
    }

}

希望这可以帮助。



 类似资料:
  • 我在SO上发现了许多类似问题的例子,但不幸的是,没有一个答案符合我的要求。 我对纵向和横向有不同的布局,并且我使用了后退堆栈,这既阻止了我使用又阻止了使用配置更改例程的技巧。 我在TextViews中向用户显示某些信息,这些信息不会保存在默认处理程序中。在单独使用活动编写应用程序时,以下操作非常有效: 对于s,这只在非常特定的情况下起作用。具体地说,最可怕的是替换一个片段,把它放在后面的堆栈中,然

  • 我有4个按钮来替换活动中的片段[片段A,片段B,片段C,片段D],然后我将片段A替换为活动,然后我将片段A中的值更改为片段A,之后我将片段B替换为片段A,并将片段C替换为片段B.但是我想把片段A替换成片段C。如何在片段A中保存状态。 当我提交片段时编写代码 要替换的图表 片段A ------- 片段B ------- 片段C ------- PS.我不想使用返回按钮返回片段A,我想替换片段A并在第

  • 我有一个HomeActivity,我从中调用片段列表。在HomeActivity中,我有一个侧菜单,其中加载了所有片段。 现在,在这个列表中,我有一个名为HomeFraank的片段,它使用webservice显示带有数据的Google地图。 我想要的是我想加载Map dat只加载一次(第一次)片段,而不是每次单击sidemenu或从任何其他片段进来时。 我的HomeFragment或任何其他片段会

  • 我编写了一个在两个片段之间切换的虚拟活动。从FragmentA到FragmentB时,FragmentA被添加到后面的堆栈中。但是,当我返回到FragmentA时(按下back),创建了一个全新的FragmentA,并且丢失了它所处的状态。我感觉我在寻找与这个问题相同的东西,但我包含了一个完整的代码示例来帮助解决这个问题: 然而,如果在删除片段时调用addToBackStack(),则该片段将被停

  • 我想在这个导航用例中避免这种情况:A- 其中所有片段实例都保存在后栈中。原因:避免内存溢出错误。 我尝试创建一个自己的导航工作流,如下所述:https://stackoverflow.com/questions/18041583/fragments-backstack-issue?noredirect=1#comment26393904_18041583(它应该模仿活动行为,在开始一个新操作后调用

  • 我需要检查堆栈中是否有重复项(仅在基本方法pop、push、top、isempty中使用),如果堆栈没有重复项,则返回true;如果堆栈为空,则返回true;如果堆栈有重复项,则返回false 如果不使用另一个函数和最短路径,我如何做到这一点?解决方案需要使用基本方法,而不使用c的内置函数#