savedInstanceState 在片段中始终为 null

Posted

技术标签:

【中文标题】savedInstanceState 在片段中始终为 null【英文标题】:savedInstanceState is always null in fragments 【发布时间】:2014-02-21 00:10:50 【问题描述】:

下面是我的代码:

public class MyListFragmentActivity extends FragmentActivity

@Override
    public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    System.out.println("DEBUG : MLFA onCreate");
    if (savedInstanceState == null) 
        getSupportFragmentManager().beginTransaction().replace(fragmentID, new MyListFragment())
            .replace(detailFragmentID, new MyDetailFragment()).commit();
        
    



     @Override
    protected void onRestart() 
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            Fragment prevFrag = getSupportFragmentManager().findFragmentById(detailFragmentID);
    if (prevFrag != null) 
        fragmentTransaction.remove(prevFrag);
        getSupportFragmentManager().beginTransaction().replace(detailFragmentID, new MyDetailFragment()).commitAllowingStateLoss();
     else 
        getSupportFragmentManager().beginTransaction().replace(detailFragmentID, new MyDetailFragment()).commitAllowingStateLoss();
    

MyListFragment

public class MyListFragment extends Fragment

//When we click on each item in list view call detail fragment to relad its layout
OnItemClickListener onItemClickListener = new OnItemClickListener() 

/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        /** Getting the existing detailed fragment object, if it already exists.
        *  The fragment object is retrieved by its tag name
        * */
        Fragment prevFrag = getFragmentManager().findFragmentById(detailFragmentID);

        /** Remove the existing detailed fragment object if it exists */
        if (prevFrag != null) 
            fragmentTransaction.remove(prevFrag);
           MyDetailFragment mydetailFragment = new MyDetailFragment();
            fragmentTransaction.replace(detailFragmentID, mydetailFragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.show(getFragmentManager().findFragmentById(detailFragmentID));
            fragmentTransaction.commit();
        

MyDetailFragment

public class MyDetailFragment extends Fragment

@Override
public void onCreate(Bundle savedInstanceState) 
 setRetainInstance(true);


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
  if (savedInstanceState != null) 
    // it is not entering the inside here 


@Override
    public void onSaveInstanceState(Bundle savedInstanceState) 
    super.onSaveInstanceState(savedInstanceState);
        // saving some values
    

当我在设置setRetainInstance(true); 之后为我的设备命名时,savedInstanceState 始终为 null,那么我如何才能在此处获取我保存的值?

为什么会这样?我在这里做错了什么以及如何解决这个问题?

【问题讨论】:

【参考方案1】:

我认为您丢失了您的 instanceState,因为您总是在 onRestart() 方法中创建一个新的 Fragment 实例。

试试这个方法:

@Override
protected void onRestart() 
    Fragment prevFrag = getSupportFragmentManager().findFragmentById(detailFragmentID);
    if (prevFrag == null || !(prevFrag instanceof MyDetailFragment)) 
        getSupportFragmentManager().beginTransaction().replace(detailFragmentID, new MyDetailFragment());
    

这样,只有在没有另一个相同类型的有效 Fragment 时,您才附加一个新的 Fragment 实例。

注意 setRetainInstance(true);防止 FragmentManager 在配置更改发生时销毁您的 Fragment 实例。 所以手动销毁你的 Fragment(通过调用 .remove(...))然后用 .replace(..., new MyDetailFragment()) 初始化一个新的 Fragment 是没有意义的。这就是为什么你总是得到一个空的 savedInstanceState:你在一个新的实例中,所以没有以前保存的状态!

还请记住,在 FragmentTransaction 上调用 .commitAllowingStateLoss() 可以让 Fragment Manager 避免保存 savedInstanceState,因此只有在您真正知道自己在做什么时才应该使用它。

祝你有美好的一天! :)

【讨论】:

【参考方案2】:

根据安卓:

onSaveInstanceState() 将默认为视图调用,当且仅它有一个 id。

默认实现会为您处理大部分 UI 实例状态,方法是在层次结构中具有 id 的每个视图上调用 onSaveInstanceState(),并保存当前聚焦视图的 id(所有这些都是由 onRestoreInstanceState(Bundle)) 的默认实现恢复。

【讨论】:

以上是关于savedInstanceState 在片段中始终为 null的主要内容,如果未能解决你的问题,请参考以下文章

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

在运行时构建的 Fragment 上始终为 null savedInstanceState(导航视图)

GetLastLocation 始终返回 null

Android:将 savedInstanceState 与片段一起使用

活动被销毁后,savedInstanceState 始终为空

使用 savedInstanceState 保存片段状态