从后台堆栈恢复片段时的 savedInstanceState

Posted

技术标签:

【中文标题】从后台堆栈恢复片段时的 savedInstanceState【英文标题】:savedInstanceState when restoring fragment from back stack 【发布时间】:2012-06-22 02:56:58 【问题描述】:

我可以在删除片段时使用savedInstanceState() 保存状态,然后在将片段从返回堆栈中弹出时恢复状态吗?当我从后台堆栈恢复片段时,savedInstanceState 包始终为空。

现在,应用流程是:创建片段 -> 删除片段(添加到后台堆栈)-> 从后台堆栈恢复片段(savedInstanceState 包为空)。

以下是相关代码:

public void onActivityCreated(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    Bundle bundle = getArguments();
    Long playlistId = bundle.getLong(Constants.PLAYLIST_ID);
    int playlistItemId = bundle.getInt(Constants.PLAYLISTITEM_ID);

    if (savedInstanceState == null) 
       selectedVideoNumber = playlistItemId;
     else 
       selectedVideoNumber = savedInstanceState.getInt("SELECTED_VIDEO");
    


public void onSaveInstanceState(Bundle outState) 
        super.onSaveInstanceState(outState);
        outState.putInt(Constants.SELECTED_VIDEO, selectedVideoNumber);
    

我认为问题在于onSavedInstanceState() 在被删除并被添加到后堆栈时从未被调用。如果我不能使用 onsavedInstanceState(),还有其他方法可以解决这个问题吗?

【问题讨论】:

【参考方案1】:

onSaveInstanceState (不幸的是)在片段的正常回栈重新创建中没有被调用。查看http://developer.android.com/guide/components/fragments.html#Creating 和How can I maintain fragment state when added to the back stack? 上的答案

【讨论】:

【参考方案2】:

我喜欢将我在 onCreateView 返回的视图存储为一个全局变量,然后当我返回时,我只需检查一下:

if(mBaseView != null) 
        // Remove the view from the parent
        ((ViewGroup)mBaseView.getParent()).removeView(mBaseView);
        // Return it
        return mBaseView;
    

【讨论】:

不确定这是个好主意。如果保存对它的引用,这是否会破坏视图以释放内存的目的? 我实际上不确定,因为我没有运行任何直接测试。然而,我的想法是这样的。当您初始化布局中的所有元素时,将这些元素中的大多数设置为全局变量是标准的,因此如果在上面的示例中由于引用而无法回收基本视图,Android 将无法回收这些视图中的任何一个,从而导致相同的内存问题。 如果您需要为不同的方向膨胀不同的视图,这将不起作用。 这个解决方案救了我的命。【参考方案3】:

问题是片段需要有一个IdTag 与之关联,以便FragmentManager 跟踪它。

至少有 3 种方法可以做到这一点:

    在 xml 布局中为您的片段声明 Id

    android:id=@+id/<Id>
    

    如果您的片段容器View 有一个Id,请使用FragmentTransaction:

    FragmentTransaction  add (int containerViewId, Fragment fragment)
    

    如果您的片段没有与任何View 关联(例如无头片段),请给它一个Tag

    FragmentTransaction  add (Fragment fragment, String tag)
    

Also, see this SO answer.

【讨论】:

【参考方案4】:

FWIW,我也遇到了这个问题,但在我的情况下,onSaveInstanceState 被正确调用,当智能手机上出现新的活动片段时,我推送了我的状态数据。和你一样,onActivityCreated 被称为 w/ savedInstanceState 始终为空。恕我直言,我认为这是一个错误。

我通过创建静态 MyApplication 状态并将数据放在那里以等效于“全局变量”来解决它...

【讨论】:

以上是关于从后台堆栈恢复片段时的 savedInstanceState的主要内容,如果未能解决你的问题,请参考以下文章

如何从后台弹出片段

Android从后台堆栈中删除事务

将新片段添加到后台堆栈是不是会暂停当前片段?

来自后台堆栈的片段 onResume

片段未在后台堆栈中注册

在后台堆栈中多次防止相同的片段