Android学习笔记-recreate()方法导致fragment重复新建的问题,解决方法

Android学习笔记-recreate()方法导致fragment重复新建的问题,解决方法

今天修改一个比较奇怪的bug:
在操作一个事件的时候,使用eventbus来监听事件,断点发现有时候是会执行两次,起初以为是没有unregister。后来发现无论有没有unregister,都没用。
后面通过不断测试,发现只有在设置系统字体后,调用activity的recreate()方法会发生重复调用。
由于是在activity里面使用了4个fragment切换,我想到会不会是,recreate方法导致的fragement出现了两次,从而eventbus执行了两次。
先看一段代码:

 private void addOrShowFragment(FragmentTransaction transaction, Fragment fragment, int currentIndex) {
        if (currentFragment == fragment)
            return;
        if (currentFragment == null) {
            transaction.add(R.id.shopmallhomecontainer, fragment, tags[currentIndex]).commitAllowingStateLoss();
        } else if (!fragment.isAdded()) { // 如果当前fragment未被添加,则添加到Fragment管理器中
            transaction.hide(currentFragment).add(R.id.shopmallhomecontainer, fragment, tags[currentIndex]).commitAllowingStateLoss();
        } else {
            transaction.hide(currentFragment).show(fragment).commitAllowingStateLoss();
        }
        currentFragment = fragment;
    }

这是activity中切换fragment的代码。
调用方法如下:

 if (mainFragment == null) {
                    mainFragment = new NewsMainFragment();
                }
                addOrShowFragment(getSupportFragmentManager().beginTransaction(), mainFragment, currentIndex);

调试发现每次recreate后mainFragment 和currentFragment都会会变成空。从而导致每次recreate后会重新new一个fragment再加到fragment管理其中。
所以需要在actvivity的onSaveInstanceState中保存下当前状态,同时在oncreate中通过savedInstanceState来去除状态:
我这里采用的是保存当前的index方式,代码如下:

 @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("currentIndex", currentIndex);
    }

只需要保存一个当前的fragment是第几个。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news_main);
        bottombar = (TabBar) findViewById(R.id.shopping_mall_tabbar);
        if (savedInstanceState != null) {
            currentIndex = savedInstanceState.getInt("currentIndex");
            String curTag = tags[currentIndex];
            currentFragment = getSupportFragmentManager()
                    .findFragmentByTag(curTag);
            mainFragment = (NewsMainFragment) getSupportFragmentManager()
                    .findFragmentByTag(tags[0]);
            videoFragment = (NewsVideoFragment) getSupportFragmentManager()
                    .findFragmentByTag(tags[1]);
            miniFragment = (NewsMiniFragment) getSupportFragmentManager()
                    .findFragmentByTag(tags[2]);
            meFragment = (NewsMeFragment) getSupportFragmentManager()
                    .findFragmentByTag(tags[3]);
        }

        bottombar.setOnTabBarSelectedListener(bottombarOnItemClick);
        bottombar.selectTab(currentIndex);
    }

通过index获取当前tag,同时找到当前fragment,其他4个frament可以通过各自的tag找到。
这时候再次执行

 if (mainFragment == null) {
                    mainFragment = new NewsMainFragment();
                }
                addOrShowFragment(getSupportFragmentManager().beginTransaction(), mainFragment, currentIndex);


private void addOrShowFragment(FragmentTransaction transaction, Fragment fragment, int currentIndex) {
        if (currentFragment == fragment)
            return;
        if (currentFragment == null) {
            transaction.add(R.id.shopmallhomecontainer, fragment, tags[currentIndex]).commitAllowingStateLoss();
        } else if (!fragment.isAdded()) { // 如果当前fragment未被添加,则添加到Fragment管理器中
            transaction.hide(currentFragment).add(R.id.shopmallhomecontainer, fragment, tags[currentIndex]).commitAllowingStateLoss();
        } else {
            transaction.hide(currentFragment).show(fragment).commitAllowingStateLoss();
        }
        currentFragment = fragment;
    }

这段代码的时候mainFragment 不会为空,同时currentFragment也不会为空,而且currentFragment取得的对象和之前的对象是同一个,这样一来,eventbus就不会重复执行了~

总结:事实上很多时候我们会忽略activity的onSaveInstanceState方法,其实onSaveInstanceState还是很有用的,用以上方式不知可以解决recreate时候导致的fragment重复新建的问题,其他场景也会用到哦,比如:屏幕旋转,进入后台之后再次启动(内存不够)等等。。用好onSaveInstanceState可以是我们的程序更加健壮。

你可能感兴趣的:(android)