简体   繁体   English

savedInstanceState在片段中始终为null

[英]savedInstanceState is always null in fragments

Below is my code: 以下是我的代码:

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 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 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
    }

When i title my device after me setting the setRetainInstance(true); 当我在设置setRetainInstance(true);之后标题我的设备时setRetainInstance(true); the savedInstanceState is always null , so how can i get my saved values here ? savedInstanceState始终为null,那么如何在此处获取保存的值?

Why so? 为什么这样? What am i doing wrong here and how to fix this ? 我在这里做错了什么以及如何解决这个问题?

I think that you loose your instanceState because you alway create a new Fragment instance in your onRestart() method. 我认为你松开了你的instanceState,因为你总是在你的onRestart()方法中创建一个新的Fragment实例。

Try it this way: 试试这种方式:

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

This way you only attach a new instance of your Fragment only if there's no another valid Fragment of the same type. 这样,只有在没有相同类型的其他有效片段时,才会附加片段的新实例。

Note that setRetainInstance(true); 注意setRetainInstance(true); prevents the FragmentManager to destroy your Fragment instance when a configuration change happens. 当配置发生更改时,会阻止FragmentManager销毁Fragment实例。 So it has no sense to manually destroy your Fragment (by calling .remove(...)) and then init a new one with .replace(..., new MyDetailFragment()). 因此,手动销毁Fragment(通过调用.remove(...))然后使用.replace(...,new MyDetailFragment())初始化它是没有意义的。 This is why you always get an empty savedInstanceState: you are in a new instance, so no previous saved states! 这就是为什么你总是得到一个空的savedInstanceState:你在一个新的实例,所以没有以前保存的状态!

Also remember that calling .commitAllowingStateLoss() on a FragmentTransaction allows the Fragment Manager it to avoid saving the savedInstanceState, so you should use it only if you really know what you're doing. 还要记住,在FragmentTransaction上调用.commitAllowingStateLoss()允许片段管理器避免保存savedInstanceState,所以只有在你真正知道自己在做什么时才应该使用它。

Have a nice day! 祝你今天愉快! :) :)

According to Android: 根据Android:

onSaveInstanceState() will be called by default for a view if and only it has an id. 默认情况下,onSaveInstanceState()将为视图调用,并且只有它具有id。

The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)). 默认实现通过在具有id的层次结构中的每个视图上调用onSaveInstanceState()并保存当前聚焦视图的id(所有这些都由以下内容恢复)来为您处理大多数UI每实例状态。 onRestoreInstanceState(Bundle)的默认实现)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM