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(导航视图)
Android:将 savedInstanceState 与片段一起使用