使用BottomNavigationView+Fragment组合,出现Fragment重叠,内存不足activity被杀死后BottomNavigationView的状态

实际开发中,经常会用到底部菜单的页面框架,今天我们就使用BottomNavigaitionView+Fragment组合实现。

废话不多说,直接码砖。。。
1、创建activity_bottomnavigationview_fragment.xml




    

    

bottom_menu.xml




    

    

    
    

2、创建4个Fragment页面FragmentTab1、FragmentTab2、FragmentTab3、FragmentTab4。这里以FragmentTab1为例:

public class FragmentTab1 extends BaseFragment {

    @Override
    protected int setContentView() {
        return R.layout.fragment_item;
    }

    @Override
    protected void findViewById(View rootView) {
        TextView tv = (TextView) rootView.findViewById(R.id.id_fragment_content);
        tv.setText("tab1");
    }
}

关于BaseFragment和布局fragment_item.xml,请参考另外一篇文章ViewPager+Fragment懒加载

3、创建BottomNavigationViewFragmentActivity主页面;

public class BottomNavigationViewFragmentActivity extends AppCompatActivity {
    private BottomNavigationView bottomNavigationView;
    private Fragment mCurrentFragment = null;
    private List fragments;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bottomnavigationview_fragment);
        bottomNavigationView = (BottomNavigationView) findViewById(R.id.id_bottom_menu);
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.menu_index:
                        showFragment(0);
                        return true;
                    case R.id.menu_video:
                        showFragment(1);
                        return true;
                    case R.id.menu_audio:
                        showFragment(2);
                        return true;
                    case R.id.menu_mine:
                        showFragment(3);
                        return true;
                }
                return false;
            }
        });
        // 准备4个fragment页面
        initFragment();
        // 底部菜单默认选中第一个
        bottomNavigationView.setSelectedItemId(bottomNavigationView.getMenu().getItem(0).getItemId());
    }

    private void initFragment() {
        if (fragments != null) {
            fragments.clear();
        } else {
            fragments = new ArrayList<>();
        }
        fragments.add(new FragmentTab1());
        fragments.add(new FragmentTab2());
        fragments.add(new FragmentTab3());
        fragments.add(new FragmentTab4());
    }

    /**
     * 使用show、hide来管理fragment
     */
    private void showFragment(int position) {
        if (fragments != null && fragments.size() > 0) {
            Fragment fragment = fragments.get(position);
            if (null != fragment && mCurrentFragment != fragment) {
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                if (mCurrentFragment != null) {
                    transaction.hide(mCurrentFragment);
                }
                mCurrentFragment = fragment;
                if (!fragment.isAdded()) {
                    transaction.add(R.id.fragment_item, fragment);
                } else {
                    transaction.show(fragment);
                }
                transaction.commit();
            }
        }
    }
}

ok,到此我们的页面就写完了。运行起来看看吧。


SVID_20190116_172731_1.gif

大功告成!

问题来了!!!

使用show()和hide()来管理fragment,在内存不足时,会出现重叠现象。我们改怎么做呢?接下来,我们先来复现这个问题,怎么做呢?

如何用真机模拟内存不足而杀死后台运行的activity呢?

image.png

如图所示,打开图片中的“不保留活动”选项即可;

再次运行我们刚才写的项目,点击菜单tab3,切换到tab3页面,然后按手机home键,返回主屏幕。此时,由于我们设置了不保留后台活动,我们的项目已经被kill掉了。然后再启动我们的应用

图片发自App

如图所示,我们fragment重叠了!!!


关于fragment重叠的原因和解决办法,网上有很多,大家可以自行选择,以下是我亲测有效的方式之一

上代码:
1、重写Activity的onSaveInstanceState()方法:

@Override
    protected void onSaveInstanceState(Bundle outState) {
        List fragments = getSupportFragmentManager().getFragments();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        for (int i = 0; i < fragments.size(); i++) {
            // 循环remove掉所有的fragment
            transaction.remove(fragments.get(i));
        }
        transaction.commitAllowingStateLoss();
        super.onSaveInstanceState(outState);
    }

2、运行代码!!!


图片发自App

what? Fragment不重叠了,但是又有了新的问题,底部菜单在kill掉activity后,重新返回的时候,菜单状态还是kill掉之前的tab3,但是fragment却是tab1的,显然重新启动的时候onCreate()方法中的bottomNavigationView.setSelectedItemId(bottomNavigationView.getMenu().getItem(0).getItemId());么有起作用啊!

怎么办?

怎么办?

怎么办?

最终我的解决办法是这样的:

@Override
    protected void onSaveInstanceState(Bundle outState) {
        List fragments = getSupportFragmentManager().getFragments();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        for (int i = 0; i < fragments.size(); i++) {
            transaction.remove(fragments.get(i));
        }
        transaction.commitAllowingStateLoss();
        super.onSaveInstanceState(outState);
        // 重新设置BottomNavigationView的默认选中项
        bottomNavigationView.setSelectedItemId(bottomNavigationView.getMenu().getItem(0).getItemId());
    }

在onSaveInstanceState()中,添加bottomNavigationView.setSelectedItemId(bottomNavigationView.getMenu().getItem(0).getItemId());

大功告成!

你可能感兴趣的:(使用BottomNavigationView+Fragment组合,出现Fragment重叠,内存不足activity被杀死后BottomNavigationView的状态)