我把代码放上来 解释我全部 都有备注, 电调用此方法可以实现回栈的功能。

 //此方法 简单解释
    public void changeFragment(int containerId, Class<? extends BaseFragment> fragmentclass, Bundle bundle, boolean isReplace, boolean isBook) {
        //获取Fragment管理
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        //获取到开启事务
        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
        //通过反射过来的参数fragmentclass获取它的名字
        String simpleName = fragmentclass.getSimpleName();
        //利用名字在回退栈中进行查找此Frragment 返回的是一个Fragment但有可能是空的也就是没有的意思
        BaseFragment fragmentByTag = (BaseFragment) supportFragmentManager.findFragmentByTag(simpleName);
        //进行if判断 当我的Fragment等于NULL 的时候的情况进行if中的操作
        if (fragmentByTag == null) {
            try {
                //由于是通过反射拿到的Fragment的类所以目前没有实体的Fragment
                //但是没关系我们可以让Anroid的虚拟机进行创建也就是说咋们赋值以后虚拟机进行咋们给好的Fragment进行实例化
                //也就是动态实例化
                fragmentByTag = fragmentclass.newInstance();
                //调用事务的添加功能因为我们加了if判断当Fragment空的时候才会进来既然进来了也就是说
                //回退栈中并没有此Frahment 那么就进行添加
                // 第一个参数是 我们容器的ID , 二    我们要添加的Fragment  三,   添加Fragment的name
                fragmentTransaction.add(containerId, fragmentByTag, simpleName);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //判断Bundel 是否携带参数过来的 当不为Null的时候就是携带了参数
        if (bundle != null) {
            //此方法定义在我们的BaseFragment中  利用 BaseFragemnt中的方法进行 传递参数
            fragmentByTag.setBundle(bundle);
        }
        //此方法是判断我们的栈顶Fragment的隐藏  如果不为NULL才能隐藏为NULL隐藏会抛异常
        if (lastFragment != null) {
            //事务 的隐藏方法
            fragmentTransaction.hide(lastFragment);
        }
        //判断是否替换的boolean 类型的值 如果是true 那就进行替换 不为true 那就显示
        if (isReplace) {
            fragmentTransaction.replace(containerId, fragmentByTag, simpleName);
        } else {

            fragmentTransaction.show(fragmentByTag);
        }

//判断是否 退栈
        if (isBook) {
            fragmentTransaction.addToBackStack(simpleName);

            lastFragment = fragmentByTag;
        }

        fragmentTransaction.commit();
    }

接下来可以去看看返回键的监听方法

 //此重写是一个 监听返回键 我们点进去看一下源码
    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

源码部分

public void onBackPressed() {
        FragmentManager fragmentManager = this.mFragments.getSupportFragmentManager();
        boolean isStateSaved = fragmentManager.isStateSaved();
        if (!isStateSaved || VERSION.SDK_INT > 25) {
            if (isStateSaved || !fragmentManager.popBackStackImmediate()) {
                super.onBackPressed();
            }

        }
    }

上边源码的大概意思我进去半天也没发掘到什么有价值的东西反正返回值布尔类型 是判断是否关闭的关键,

popBackStackImmediate()  此方法是 立即退出栈的方法

接着我们去把写返回键中退栈自己的代码逻辑

 

 

 @Override
    public void onBackPressed() {
        //获取管理
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        //通过管理类可以获取到当前的栈内数量
        int backStackEntryCount = supportFragmentManager.getBackStackEntryCount();
        //当栈内数量中大于0 的时候才能进行操作不然会造成索引越界
        if (backStackEntryCount>0){
            //退栈
            supportFragmentManager.popBackStackImmediate();
            //获取一下栈内的数量
            int backStackEntryCount = supportFragmentManager.getBackStackEntryCount();
            //二次判断
            if (backStackEntryCount>0){
                //退栈完 元素 -1 就是当前的栈顶Fragemn
                FragmentManager.BackStackEntry backStackEntryAt = supportFragmentManager.getBackStackEntryAt(backStackEntryCount - 1);
                //重新过去name
                String name = backStackEntryAt.getName();
                //重新获取 Fragment
                BaseFragment fragmentByTag = (BaseFragment) supportFragmentManager.findFragmentByTag(name);
                //重新赋值
                lastFragment=fragmentByTag;

            }else {
                finish();
            }

        }

    }