Android Fragment重叠问题

前言:最近项目中用BottomNavigationView动态添加几个Fragment于FrameLayout中,bug就在我切换其他APP操作一会后,再回到当前APP,有很大概率出现fragment重叠的现象。

Android Fragment重叠问题_第1张图片


一、Fragment 重叠原因分析

切换到其他APP时,Android由于内存资源紧张,fragmen所在activity已经被销毁,但是保存了activity的状态:

Android有一个种特殊情况,就是app运行在后台的时候,内存资源紧张的时候导致把app的资源全部回收(销毁Activity),这时把app再从后台返回到前台时,app会重启Activity。

这属于非正常销毁,尽管Activity实例被销毁,但系统会调用Activity的onSaveInstanceState()保存其状态,这样,如果用户导航回该Activity,系统会使用onCreate中的参数savedInstanceStatea保存的状态数据恢复之前的fragment,并重新创建activity新实例,这样相当于又再次add了fragment进去,所以出现了重叠现象。


二、解决方案:(亲测有效)

findFragmentbyTag:

即在add()或replace()时绑定一个tag,一般用fragment的类名作为tag,然后在发生“内存重启”时,通过findFragmentByTag()找到对应的Fragment显示show(),并hide()需要隐藏的fragment。

/*2、解决内存重启后碎片的重叠问题 */
    private void initFragmen(Bundle savedInstanceState)
    {
        if(savedInstanceState != null)
        {
            // “内存重启”时调用
            homepageFragment = (HomepageFragment)getSupportFragmentManager().findFragmentByTag("homepageFragment");
            hotFragment = (HotFragment)getSupportFragmentManager().findFragmentByTag("hotFragment");
            meFragment  = (MeFragment)getSupportFragmentManager().findFragmentByTag("meFragment");

            //取出onSaveInstanceState(Bundle outState)里保存离开时的那个界面的tag,恢复到用户离开时的那个Fragment的界面
            String tag = savedInstanceState.getString("lastVisibleFragment");

            switch (tag)
            {
                case "homepageFragment":
                    // 解决重叠问题
                    getSupportFragmentManager().beginTransaction()
                            .show(homepageFragment)
                            .hide(hotFragment)
                            .hide(meFragment)
                            .commit();
                    break;

                case "hotFragment":
                    // 解决重叠问题
                    getSupportFragmentManager().beginTransaction()
                            .show(hotFragment)
                            .hide(homepageFragment)
                            .hide(meFragment)
                            .commit();
                    topView.setVisibility(View.GONE);
                    toolbar.setVisibility(View.GONE);

                    break;

                case "meFragment":
                    // 解决重叠问题
                    getSupportFragmentManager().beginTransaction()
                            .show(meFragment)
                            .hide(hotFragment)
                            .hide(homepageFragment)
                            .commit();
                    topView.setVisibility(View.GONE);
                    toolbar.setVisibility(View.GONE);
                    break;
            }

        }
        else
        {
            // 正常创建时
            homepageFragment = new HomepageFragment();
            hotFragment = new HotFragment();
            meFragment = new MeFragment();

            getSupportFragmentManager().beginTransaction()
                    .add(R.id.content_fragment_layout,homepageFragment, "homepageFragment")
                    .add(R.id.content_fragment_layout,hotFragment,"hotFragment")
                    .add(R.id.content_fragment_layout,meFragment,"meFragment")
                    .show(homepageFragment)
                    .hide(hotFragment)
                    .hide(meFragment)
                    .commit();
        }

    }


三、恢复到用户离开时的那个Fragment的界面

如果你想恢复到用户离开时的那个Fragment的界面,你还需要在onSaveInstanceState(Bundle outState)里保存离开时的那个界面的tag或者下标,在“内存重启”代码块中,取出tag/下标,进行恢复。

/*5、内存销毁活动后,保存ctivity中当前显示的fragment的tag*/
   @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        lastVisibleFragment = getVisibleFragment();
        outState.putString("lastVisibleFragment",lastVisibleFragment.getTag());
   }


四、得到Activity当前显示的fragment

    /*6、得到当前Activity显示的fragment*/
    private Fragment getVisibleFragment()
    {
        Fragment lastFragment = null;
        fragmentManager = getSupportFragmentManager();
        fragmentList = fragmentManager.getFragments();
        for(Fragment fragment : fragmentList)
        {
            if (fragment != null && fragment.isVisible())
            {
                lastFragment = fragment;
                break;
            }
        }
        return lastFragment;
    }



你可能感兴趣的:(Android)