Android学习知识android故事累积Android开发经验谈

Fragment的状态保存与恢复导致的重叠

2017-07-14  本文已影响287人  cuixbo

我们在开发过程中有时会遇到Fragment内容重叠的情况,其具体原因可以参考这篇文章:从源码角度分析,为什么会发生Fragment重叠?

简单说就是Support 24.0.0之前的Fragment在onSaveInstanceState()时并没有保存mHidden状态,导致Activity在重新创建后恢复Fragment时其被新创建的恢复的fragment都是默认为show状态的,引起了内容重叠.

其实上面的文章中也提到了解决办法,不过对于Activity中的处理方式没有进行具体说明,下面我讲列出我的示例代码说明一下:

Fragment的修改:
public class BaseFragment extends Fragment {
    private static final String STATE_SAVE_IS_HIDDEN = "STATE_SAVE_IS_HIDDEN";
    protected Context mContext;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        log();
        //fragment恢复后,恢复到原来的show,hide状态
        if (savedInstanceState != null) {
            boolean isSupportHidden = savedInstanceState.getBoolean(STATE_SAVE_IS_HIDDEN);
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            if (isSupportHidden) {
                ft.hide(this);
            } else {
                ft.show(this);
            }
            ft.commitAllowingStateLoss();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        log();
        outState.putBoolean(STATE_SAVE_IS_HIDDEN, isHidden());
    }
}
Activity中对于Fragment的创建于恢复使用:
public class MainActivity extends BaseActivity {

    private BottomNavigationBar bottomNavigationBar;
    private FragmentManager fragmentManager;
    private final static String TAG_HOT = "热映";
    private final static String TAG_EXPLORER = "找片";
    private final static String TAG_MINE = "我的";
    private final static String[] TAGS = new String[]{"热映", "找片", "我的"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initListener();
        bottomNavigationBar.selectTab(0);
    }

    private void initView() {
        fragmentManager = getFragmentManager();
        bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
        bottomNavigationBar
                .addItem(new BottomNavigationItem(R.drawable.ic_hot_normal, "热映"))
                .addItem(new BottomNavigationItem(R.drawable.ic_explore_normal, "找片"))
                .addItem(new BottomNavigationItem(R.drawable.ic_mine_normal, "我的"))
                .setMode(BottomNavigationBar.MODE_FIXED)
                .initialise();
    }

    private void initListener() {
        bottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
            @Override
            public void onTabSelected(int position) {
                FragmentTransaction transaction = fragmentManager.beginTransaction();
                Fragment fragment = fragmentManager.findFragmentByTag(TAGS[position]);
                if (fragment == null) {
                    switch (position) {
                        case 0:
                            fragment = new HotMovieFragment();
                            break;
                        case 1:
                            fragment = new ExploreMovieFragment();
                            break;
                        case 2:
                            fragment = new MineFragment();
                            break;
                    }
                    if (fragment != null) {
                        transaction.add(R.id.fl_fragment_container, fragment, TAGS[position]);
                    }
                } else {
                    transaction.show(fragment);
                }
                transaction.commitAllowingStateLoss();
            }

            @Override
            public void onTabUnselected(int position) {
                FragmentTransaction transaction = fragmentManager.beginTransaction();
                Fragment fragment = fragmentManager.findFragmentByTag(TAGS[position]);
                if (fragment != null) {
                    transaction.hide(fragment);
                    transaction.commitAllowingStateLoss();
                }
            }

            @Override
            public void onTabReselected(int position) {

            }
        });
    }
}

需要注意的是:
transaction.add(R.id.fl_fragment_container, fragment, tag);
上面这行代码要慎用,因为Activity重建后,之前的Fragment会被系统重新恢复,如果Activity重建后你在Activity中再次add的话就会可能出现重叠的情况.这种情况下就不用再去创建了,而是应该找到系统给我们恢复了的那些Fragment,
Fragment fragment = fragmentManager.findFragmentByTag(tag);
用上面这行代码就可以找到我们恢复的fragment,如果为空我们再去创建新的.

关于Activity,Fragment重建的个人理解:

所谓Activity重建,其实应该是系统保存了Activity的状态,系统给重新创建了个新的Activity实例并且恢复了之前保存的销毁的那个Activity的状态,使得Activity像是被重启了一样,新创建的其实是一个全新的Activity,其成员变量等都是新实例的.同样,Fragment也是如此,系统会恢复之前保存的销毁了的Fragemnt的状态,而重新创建Fragment,这些重新创建的Fragment可以通过FragmentManager的findFragmentByTag()方法来获取到.

至此,我们就明白了Fragment的保存与恢复了吧.

上一篇下一篇

猜你喜欢

热点阅读