当前位置: 首页 > 知识库问答 >
问题:

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

谢英光
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并且当它的视图不再存在时会调用此方法,因此在TextView的任何结果中查找NullPointerException

此外,我发现,保留对textviews的引用对fragment不是一个好主意,即使对activity是可以的。在这种情况下,OnSaveInstanceState()实际上保存了状态,但如果在隐藏片段时旋转屏幕两次,则问题再次出现,因为在新实例中没有调用其OnCreateView()

我曾想过将onDestroyView()中的状态保存到一些Bundle类型的类成员元素中(实际上是更多的数据,而不仅仅是一个TextView)并将其保存到onSaveInstanceState()中,但存在其他缺陷。首先,如果当前显示的是片段,那么调用两个函数的顺序是颠倒的,所以我需要考虑两种不同的情况。必须有更干净正确的解决方案!

共有1个答案

越飞鸾
2023-03-14

要正确保存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.重要的一点是,在activity中,必须将片段的实例保存在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中向用户显示某些信息,这些信息不会保存在默认处理程序中。当仅使用“活动”编写我的应用程序时,以下方法运行良好: 使用,这仅在非常特殊的情况下有效。具体地说,令人震惊的是替换片段,将其放回堆栈中

  • 我在我的android应用程序中使用导航抽屉,当我重新选择片段时,它会加载两次。 以下是我的代码 在每个片段中,我都使用异步任务,当我选择片段时,异步任务一次又一次地启动 请帮助我

  • 当我在导航抽屉中的不同片段之间切换时,我试图保存导航抽屉片段上的状态。例如:我从片段A开始触发一些事件,然后切换到片段B。然后我想在从片段B切换回片段A时看到片段A的相同状态。 我尝试使用onSavedInstanceState(Bundle savedInstanceState),但只有当片段生命周期中的方向发生变化时才会调用它。每当我切换到新片段时,都会创建一个新片段,我不知道如何从片段中保存

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

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

  • Android Jetpack导航,BottomNavigationView带自动碎片返回堆栈返回按钮点击? 我想要的,在用户选择多个选项卡后,用户点击返回按钮后,应用程序必须重定向到他/她打开的最后一个页面。 我使用Android ViewPager实现了同样的功能,将当前选定的项保存在ArrayList中。Android Jetpack导航发布后是否有自动后退堆栈?我想用导航图实现它 acti