屏幕旋转后不会出现嵌套的碎片

时间:2015-08-12 10:09:22

标签: android android-fragments

我有这种情况,

活动 - > RestaurantsFragment - > [viewPager / FragmentPageAdapter]两个片段

我希望在屏幕旋转后保留所有片段,但会发生什么

  • 正确销毁并重新创建活动
  • 正确保留RestaurantsFragment并重新附加到活动
  • 这两个片段没有出现。他们的方法onAttach,onCreateView等...没有被调用

这是我的代码......

Activity.java

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    ....

    if (savedInstanceState== null) {
        fragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAGMNET_RESTAURANTS);
        if(fragment==null) {
            fragment = new RestaurantsFragment();
        }
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.frame_container, fragment, (TAG_FRAGMNET_RESTAURANTS);

    }

    ....
  }

RestaurantsFragment.java

    private TabsRestaurantsAdapter tabsRestaurantsAdapter;
    private ViewPager viewPager;
    private int position;


  @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("Luigi-RFragment-" + id, "onCreate");

        setRetainInstance(true);


        Log.d("Luigi-RFragment-" + id, "savedInstanceState==null");
        tabsRestaurantsAdapter = new TabsRestaurantsAdapter(getChildFragmentManager());

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d("Luigi-RFragment-" + id, "onCreateView");

        View rootView = inflater.inflate(R.layout.ristoranti_fragment, container, false);

        viewPager = (ViewPager) rootView.findViewById(R.id.pager);
        viewPager.setAdapter(tabsRestaurantsAdapter);

        position = 0;
        if (savedInstanceState != null) {
            position = savedInstanceState.getInt("position");
        }

        viewPager.setCurrentItem(position);

        setHasOptionsMenu(true);

        return rootView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt("position", viewPager.getCurrentItem());
    }

TabsRestaurantsAdapter.java

public class TabsRestaurantsAdapter extends FragmentPagerAdapter {

    private String titles[] = new String[]{"I TUOI PREFERITI", "TUTTI"};
    private MenusFavTabFragment menusFavTabFragment;
    private RestaurantsAllTabFragment restaurantsAllTabFragment;

    public TabsRestaurantsAdapter(FragmentManager fm) {
        super(fm);

        menusFavTabFragment = new MenusFavTabFragment();
        restaurantsAllTabFragment = new RestaurantsAllTabFragment();
    }

    @Override
    public Fragment getItem(int index) {
        Log.d("Luigi-adapter", "getItem" + index);
        switch (index) {
            case 0:
                // Favourite Fragment
                return menusFavTabFragment;

            case 1:
                // All Restaurant
                return restaurantsAllTabFragment;

        }

        return null;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment f = (Fragment) super.instantiateItem(container, position);
        return f;
    }

    public CharSequence getPageTitle(int position) {
        return titles[position];
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return titles.length;
    }

}

考虑重新连接RestaurantsFragment时,在viewPager中再次设置适配器(旧),并调用适配器 instantiateItem 的方法

嵌套的两个片段没什么特别的

(我还尝试每次都重新创建一个新的适配器(管理旧片段的重用)并且它只能进行一次轮换...但为什么我要重新创建适配器呢?)

他们为什么不出现?

感谢。

3 个答案:

答案 0 :(得分:1)

这是支持库v4中的一个错误。

了解更多信息Nested fragments not being retained in support library

就个人而言,我将清单上的配置更改设置为orientationscreenSize。我没有给自己一点时间想出更好的方法;)

答案 1 :(得分:1)

谢谢谢谢谢谢@hegazy

我发现并应用了此解决方法,现在它可以正常运行:

保留childFragmentManager并将其重新分配给Field对象

新的 RestaurantsFragment.java

    //the global childFragmentManager
    private FragmentManager mRetainedChildFragmentManager;

    public void onAttach(Activity activity) {
        super.onAttach(activity);

        //To fix the bug with library v4
        if (mRetainedChildFragmentManager != null) {
            //restore the last retained child fragment manager to the new
            //created fragment
            try {
                Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager");
                childFMField.setAccessible(true);
                childFMField.set(this, mRetainedChildFragmentManager);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            mRetainedChildFragmentManager = getChildFragmentManager();
        }

    }

我希望这可以帮到你!

答案 2 :(得分:0)

这似乎在支持库版本24中得到修复。

对变通方法中显示的对onAttach()的调用是在旋转期间在包含活动的super.onCreate()方法中导致NPE。一时兴起,我删除了onAttach()代码,因为这个NPE只发生在我实现解决方案的Activity / Fragment中。删除对onAttach()的调用后,NPE消失了,好像我的代码按预期工作了。

请参阅:https://code.google.com/p/android/issues/detail?id=197271