21

我已经看到了一些类似的问题,关于onSaveInstanceState不被要求Fragments,但在我的情况下Fragment,s 工作正常,这是遇到问题的主要FragmentActivity问题。

相关代码看起来相当简单:

public class MyFActivity extends FragmentActivity implements ActionBar.TabListener { 
    String[] allValues; // data to save

    @Override
    protected void onSaveInstanceState (Bundle outState) {
        Log.d("putting it!", allValues.toString());
        outState.putStringArray("allValues", allValues);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            allValues = savedInstanceState.getStringArray("allValues");
            Log.d("getting it!", allValues.toString());
        }
    }
}

暂停活动时(使用后退按钮),onSaveInstanceState永远不会调用 ,因此,在恢复应用程序时savedInstanceState始终null位于方法内。onCreate我尝试添加这样的块:

@Override
public void onPause() {
    super.onPause();
    onSaveInstanceState(new Bundle());      
}

这是在https://stackoverflow.com/a/14195202/362657中提出的,但在onSaveInstanceState随后被调用时,savedInstanceState仍保留nullonCreate方法中。我错过了什么?

4

3 回答 3

84

这里的问题是你误解了它是如何onSaveInstanceState工作的。它旨在保存Activity/的状态,Fragment以防操作系统因内存原因或配置更改而需要销毁它。onCreate然后,当Activity/Fragment返回 / 重新启动时,此状态会被传回。

在 aFragment中,它们的所有生命周期回调都直接绑定到它们的父级Activity。所以onSaveInstanceStateFragment它的父级调用时ActivityonSaveInstanceState调用。

暂停活动时(使用后退按钮),永远不会调用 onSaveInstanceState,因此,在恢复应用程序时,onCreate 方法中的 savedInstanceState 始终为 null。

当按下返回时,用户正在销毁Activity,因此它的孩子Fragments,因此没有理由调用onSaveInstanceState,因为实例正在被销毁。当你重新打开 时Activity,它是一个全新的实例,没有保存状态,所以Bundle传入的onCreatenull. 这完全符合设计。但是,尝试旋转设备或点击主页按钮,然后您会看到Activity和它的孩子Fragment已经onSaveInstanceState调用,并在onCreate返回时传回。

您添加的直接在 内部调用的hack是一种非常糟糕的做法,因为您永远不应该直接调用生命周期回调。这样做会使您的应用程序进入非法状态。onSaveInstanceState(new Bundle());onPause

如果您真正想要的是让您的数据在您的应用程序实例之外持续存在,我建议您考虑使用SharedPreferences数据库获取更高级的数据。然后,您可以将持久数据保存在onPause()其中或在其更改时保存。

希望这可以帮助。

于 2013-04-10T20:31:39.770 回答
10

在对已接受答案的更新中:

onSaveInstanceState如果您使用ViewPager带有FragmentStatePagerAdapter(而不是FragmentPagerAdapter)的片段,则可能会调用片段

FragmentStatePagerAdapter

当有大量页面时,此版本的寻呼机更有用,更像列表视图。当页面对用户不可见时,它们的整个片段可能会被销毁,只保留该片段的已保存状态。与 FragmentPagerAdapter 相比,这允许分页器保留与每个访问的页面相关联的内存少得多,但代价是在页面之间切换时可能会产生更多开销。

不要忘记:

使用 FragmentPagerAdapter 时,主机 ViewPager 必须设置有效的 ID。

于 2014-01-29T18:31:00.487 回答
0

不是对这个问题的准确答案,但可能会对某人的一天有所帮助。就我而言,我打电话给

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
  super.onSaveInstanceState(outState, outPersistentState);
}

我将上面的代码替换如下,一切正常

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
}
于 2020-07-30T14:38:18.413 回答