美文网首页四大组件
Fragment(11)——回退栈管理

Fragment(11)——回退栈管理

作者: 奔跑的佩恩 | 来源:发表于2019-08-12 16:29 被阅读0次

    前言

    在Fragment的使用过程中,我们经常会遇到Fragment的启动和关闭的问题,我们当然可以使用add及remove系列方法来实现Fragment的创建和移除,但是这样会导致Fragment频繁的创建和销毁,对程序的性能具有极大影响。为了方便实现Fragment的创建和销毁时机,以及对Fragment实现向Activity一样的管理,我们可以使用Fragment的回退栈。

    今天涉及的内容有:

    1. Fragment回退栈相关的几个重要方法
    2. Fragment回退栈管理类FragmentStackManager简介
    3. FragmentStackManager管理Fragment实例讲解
    4. 效果图
    5. FragmentStackManager源码

    先上波效果图:
    下面这张是FragmentThree返回到FragmentOne的所有操作:


    1.gif

    下面这张是FragmentThree关闭所有Fragment的所有操作:


    2.gif
    项目结构图如下:
    image.png

    一. Fragment回退栈相关的几个重要方法

    Fragment回退栈管理相关的几个方法主要和 FragmentTransaction 及 FragmentManager相关,其中 FragmentTransaction 涉及到向回退栈中添加Fragment,以下给出代码示例:

    FragmentManager manager= ((FragmentActivity)context).getSupportFragmentManager();
    Fragment fragment=manager.findFragmentByTag(tag);
    //添加fragment到回退栈
    transaction.addToBackStack(tag);
    //其他代码省略
    //......
    

    弹出栈顶最后一个Fragment(弹出后此Fragment会被销毁)

    fragmentManager.popBackStack();
    

    获取回退栈中Fragment个数

    fragmentManager.getBackStackEntryCount();
    

    销毁回退栈中部分Fragment

    fragmentManager.popBackStackImmediate(name,flag);
    

    这里对popBackStackImmediate方法参数做一个解释:
    方法中第二个参数 flag 只能是 0 或者 1(POP_BACK_STACK_INCLUSIVE)

    • 当第一个参数为 null,第二个参数为 0 时,会弹出栈顶的一个fragment
    • 当第一个参数为 null,第二个参数为 1 (POP_BACK_STACK_INCLUSIVE)时,会清空回退栈中所有fragment
    • 当第一个参数为fragment的tag,第二个参数为1(POP_BACK_STACK_INCLUSIVE)时,会弹出该状态(包括该状态)以上的所有状态

    二. Fragment回退栈管理类FragmentStackManager简介

    我将Fragment回退栈的相关方法封装到FragmentStackManager类中,现在对FragmentStackManager中一些方法做些简单介绍:

    跳转Fragment界面时,添加fragment到回退栈中

        /***
         * 跳转fragmnet并添加到回退栈
         * 
         * @param containerId 装fragment的控件id,一般是FrameLayout的id
         * @param context 上下文
         * @param tag fragment对应的tag
         * @param bundle 传值用的bundle
         * @param listener 创建一个frgmment实例的监听
         * @return
         */
        public Fragment startFragment(int containerId, Context context, String tag, Bundle bundle, OnCreateFragmentListener listener)
    

    关闭当前Fragment

    public void finish(Context context)
    

    根据之前fragment界面的tag,返回到那个fragment界面并关闭当前Fragment和要返回fragment界面之间的fragment,包括关闭当前的fragment

        /***
         * 返回到指定已经打开的fragment,并关闭当前及当前与指定Fragment间的所有Fragment
         * @param tag 需要返回到指定Fragment的tag
         *            若你需要返回到FragmentOne,且FragmentOne的tag为“one”,则此处tag参数填“one”
         * @param context
         */
        public void goBackToFragmentByTag(String tag,Context context)
    

    关闭所有Fragment

    public void finishAllFragments(Context context)
    

    获取回退栈中fragment个数

    public int getFragmentSize(Context context)
    

    获取回退栈中所有Fragment对应的tag的集合

    public List<String> getFragmentTags(Context context)
    

    三. FragmentStackManager管理Fragment实例讲解

    下面来讲解下FragmentStackManager在实际中的使用。
    创建三个Fragment:FragmentOne,FragmentTwo和 FragmentThree,每个Fragment中都是两个按钮,一个textview,按钮用于处理返回和跳转,textview用来显示当前是哪一个Fragment。
    以FragmentOne为例,其对应的布局 fragment_one.xml代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:background="@color/white">
    
        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="第一个Fragment"
            app:layout_constraintHorizontal_bias="0.494"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="Button"
            android:textAllCaps="false"
            app:layout_constraintEnd_toStartOf="@+id/button2"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv" />
    
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textAllCaps="false"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/button"
            app:layout_constraintTop_toTopOf="@+id/button" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    FragmentOne的代码如下:

    public class FragmentOne extends AppFragment {
    
        private TextView mTv;
        private Button mBtn;
        private Button mBtn2;
    
        private FragmentTwo mFragmentTwo;
    
        @Override
        public int getContentViewId() {
            return R.layout.fragment_one;
        }
    
        @Override
        public void initData() {
            //初始化控件
            initView();
        }
    
        private void initView(){
            mTv=getView(R.id.tv);
            mBtn=getView(R.id.button);
            mBtn2=getView(R.id.button2);
    
            mBtn.setText("返回");
            mBtn2.setText("跳转fragment2");
        }
    
        @Override
        public void setListener() {
            mBtn.setOnClickListener(this);
            mBtn2.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            super.onClick(v);
    
            switch (v.getId()) {
                case R.id.button://返回
                    FragmentStackManager.getInstance().finish(mContext);
                    break;
                case R.id.button2://跳转fragment2
                    mFragmentTwo= (FragmentTwo) FragmentStackManager.getInstance().startFragment(R.id.fr, mContext, "two", null, new FragmentStackManager.OnCreateFragmentListener() {
                        @Override
                        public Fragment createFragment() {
                            return new FragmentTwo();
                        }
                    });
                    break;
                default:
                    break;
            }
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
            LogUtil.i("========fragment1销毁=====");
        }
    }
    

    其他Fragment逻辑相似,大体思路是,在MainActivity中点击按钮,跳转到FragmentOne,FragmentOne点击返回可以关闭当前Fragment到MainActivity中,点击右侧按钮可以跳转到FrgmentTwo,FragmentTwo中有两个按钮,一个用于关闭当前界面,一个用于跳转FrargmentThree,然后FragmentThree中两个按钮,一个用于关闭当前界面,返回到上一个Fragment界面,另一个按钮用作其他处理。
    ok,现在让我们看看MainActivity中代码:

    public class MainActivity extends AppFragActivity {
    
        private TextView mTv;
        private Button mBtn;
        private Button mBtn2;
        private FrameLayout mFrLayout;
    
        private FragmentOne mFragmentOne;
    
        @Override
        public int getContentViewId() {
            return R.layout.activity_main;
        }
    
        @Override
        public void initData() {
            initView();
    
            mBtn.setText("跳转fragment");
            mBtn2.setText("回退栈个数");
        }
    
        private void initView(){
            mTv=getView(R.id.tv);
            mBtn=getView(R.id.button);
            mBtn2=getView(R.id.button2);
            mFrLayout=getView(R.id.fr);
    
            LogUtil.i("=====最新测试===1===");
        }
    
        @Override
        public void setListener() {
            mBtn.setOnClickListener(this);
            mBtn2.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            super.onClick(v);
    
            switch (v.getId()) {
                case R.id.button:
                    mFragmentOne= (FragmentOne) FragmentStackManager.getInstance().startFragment(R.id.fr, mContext, "one", null, new FragmentStackManager.OnCreateFragmentListener() {
                        @Override
                        public Fragment createFragment() {
                            return new FragmentOne();
                        }
                    });
                    break;
                case R.id.button2:
                    //回退栈中fragment个数
                    int count=FragmentStackManager.getInstance().getFragmentSize(mContext);
                    LogUtil.i("=====回退栈中fragment个数===="+count);
    
                    List<String>fragmentTags=FragmentStackManager.getInstance().getFragmentTags(mContext);
                    //遍历fragment的tag
                    for (String tag : fragmentTags) {
                        LogUtil.i("====fragmentTag==="+tag);
                    }
    
                    break;
                default:
                    break;
            }
    
        }
    }
    

    其中AppFragActivity 是封装的一个继承自AppCompatActivity的基类,类似于大家常用的BaseActivity,button用于跳转到FragmmentOne,button2用于统计回退栈中Fragment个数,并打印Fragment对应的tag。FragmentTwo中两个按钮事件代码如下:

        public void onClick(View v) {
            super.onClick(v);
    
            switch (v.getId()) {
                case R.id.button://返回
                    FragmentStackManager.getInstance().finish(mContext);
                    break;
                case R.id.button2://跳转fragment3
                    mFragmentThree= (FragmentThree) FragmentStackManager.getInstance().startFragment(R.id.fr, mContext, "three", null, new FragmentStackManager.OnCreateFragmentListener() {
                        @Override
                        public Fragment createFragment() {
                            return new FragmentThree();
                        }
                    });
                    break;
                default:
                    break;
            }
        }
    

    一个用于关闭当前界面,一个用于跳转到FragmentThree。
    在FragmentThree中两个按钮事件如下:

        @Override
        public void onClick(View v) {
            super.onClick(v);
    
            switch (v.getId()) {
                case R.id.button://返回
                    FragmentStackManager.getInstance().finish(mContext);
                    break;
                case R.id.button2://跳转到fragment1
                    //返回到FragmentOne
                    FragmentStackManager.getInstance().goBackToFragmentByTag("one",mContext);
    
    //                //关闭所有Fragment
    //                FragmentStackManager.getInstance().finishAllFragments(mContext);
                    break;
                default:
                    break;
            }
        }
    

    button按钮用于关闭当前Fragment,button2中有两个方法,一个用于返回到FragmnetOne并关闭faragmmentTwo和FragmentThree,另一个方法用于关闭所有fragment。

    四. 效果图

    下面这张是FragmentThree返回到FragmentOne的所有操作:


    1.gif

    下面这张是FragmentThree关闭所有Fragment的所有操作:


    2.gif

    五. FragmentStackManager源码

    下面给出 FragmentStackManager管理类代码:

    相关文章

      网友评论

        本文标题:Fragment(11)——回退栈管理

        本文链接:https://www.haomeiwen.com/subject/emfljctx.html