首页 > 其他分享 >Fragment回退栈相关操作

Fragment回退栈相关操作

时间:2023-02-15 10:46:23浏览次数:39  
标签:Fragment FragmentManager 回退 操作 fragmentManager Stack getSupportFragmentManager

在我的场景里,会创建多个Fragment,Fragment之间可以互相跳转,点击返回键需要一级一级往上返回。因此需要一个类似于Activity的回退栈,当然没必要做到Activity那么复杂,满足先进先出的效果即可。

添加Fragment回退栈

添加个Fragment,并将其加入回退栈,代码如下:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
        .add(R.id.frag_container, fragment)
        .addToBackStack(null)
        .commitAllowingStateLoss();

方法addToBackStack表示将Fragment加入到回退栈中。
在返回时,Fragment出栈的逻辑如下:

FragmentManager fragmentManager = getSupportFragmentManager();
int backStackCount = fragmentManager.getBackStackEntryCount();
if (backStackCount > 0) {
    fragmentManager.popBackStack();
}

方法popBackStack将一个Fragment出栈,调用前可以先通过getBackStackEntryCount方法判断当前回退栈是否还有Fragment。

获取顶部的Fragment

我的场景中,经常要获取栈顶的Fragment进行操作,然而没有找到直接获取栈顶Fragment的方法。在最初的实现中,借用了Stack来实现我的逻辑。

private final Stack<Fragment> mFragmentStack = new Stack<>();

public void addFragment(Fragment fragment) {
    FragmentManager fragmentManager = getSupportFragmentManager();
	fragmentManager.beginTransaction()
        .add(R.id.frag_container, fragment)
        .addToBackStack(null)
        .commitAllowingStateLoss();
	mFragmentStack.push(fragment);
}

public void popFragment() {
    FragmentManager fragmentManager = getSupportFragmentManager();
	int backStackCount = fragmentManager.getBackStackEntryCount();
	if (backStackCount > 0) {
    	    fragmentManager.popBackStack();
            mFragmentStack.pop();
	}
}

public Fragment getTopFragment() {
    return mFragmentStack.peek();
}

然而使用Stack后发现线上版本会发生crash。mFragmentStack里的Fragment和FragmentManager中的Fragment可能不一致。主要原因是Activity状态恢复导致的,Stack数据没有saveInstanceState,Activity恢复时执行mFragmentStack.peek会导致EmptyStackException
要修复这个问题,可以将Stack数据也进行状态保存。但我仔细想过后觉得,Stack和FragmentManager的作用是一致的,加一个Stack本身是不合理的,后续代码变更,也很难保证Stack和FragmentManager回退栈数据是一致的。为此我开始想另外的解决方案。
回到我最开始的需求,我就是想获取顶部的Fragment,能不能用FragmentManager提供的接口来实现呢?阅读相关源码后,有个方法引起了我的注意:

/**
 * Return the BackStackEntry at index <var>index</var> in the back stack;
 * entries start index 0 being the bottom of the stack.
 */
@NonNull
public BackStackEntry getBackStackEntryAt(int index) {
    return mBackStack.get(index);
}

获取到的BackStackEntry有id和name属性,为此我想到一个办法:

public Fragment getTopFragment() {
    int count = getSupportFragmentManager().getBackStackEntryCount();
    FragmentManager.BackStackEntry entry = getSupportFragmentManager().getBackStackEntryAt(count - 1);
    return getSupportFragmentManager().findFragmentByTag(entry.getName());
}

该代码中,首先获取回退栈数量,然后通过getBackStackEntryAt方法,获取最后一个回退栈数据。最后通过findFragmentByTag找到顶部的Fragment。不过这里要注意的是,在添加回退栈时,需要设置tag。具体代码如下:

public void addFragment(Fragment fragment) {
    String tag = getFragmentTag();
    FragmentManager fragmentManager = getSupportFragmentManager();
	fragmentManager.beginTransaction()
        .add(R.id.frag_container, fragment, tag)
        .addToBackStack(tag)
        .commitAllowingStateLoss();
}

上面代码中,add和addToBackStack方法都指定了同一个tag,保证后续能够通过findFragmentByTag找到相应的Fragment。
方案最终验证OK。

标签:Fragment,FragmentManager,回退,操作,fragmentManager,Stack,getSupportFragmentManager
From: https://www.cnblogs.com/carvergit/p/17121921.html

相关文章

  • 文件操作的函数
    1.open头文件:#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>原型:intopen(constchar*pathname,intflags);//这种原型是打开......
  • DOM通用属性操作class属性操作
    1通用属性操作1attr():获取/设置元素的属性2removeAttr():删除属性3prop():获取/设置元素的属性4removeProp:删除属性attr和prop区别1......
  • Python文件的操作处理,一看就会
    ​每天进步一点点,关注我们哦,每天分享测试技术文章本文章出自【码同学软件测试】码同学公众号:自动化软件测试,领取资料可加:magetest码同学抖音号:小码哥聊软件测试​在读......
  • 操作系统的四大特征
    1.并发并发:操作系统同时执行多个进程(依赖CPU个数);串行:同一时间只会执行一个程序;2.共享资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用;2种共享方......
  • 操作系统的功能和目标以及接口分类
    1.功能和目的操作系统:处理器管理,存储器管理,文件管理,设备管理;目的:安全,高效;2.接口命令接口:允许用户直接使用的接口,比如代开cmd输入命令shutdown等;用户说一句,系......
  • 期末复习——操作系统概述 chapter(0+1)
    MEMOOS:管理计算机硬件的软件;为应用程序提供基础;充当计算机硬件与用户之间的媒介。存于磁盘。一个一直运行在计算机上的程序(也叫kernel内核);计算机系统可以粗分为:硬......
  • 操作系统
    操作系统的概述重点:操作系统是硬件和语言处理程序之间的中间层一些操作系统的特点重点:嵌入式炒作系统,要求微型化,可定制,易移植,实时性,可靠性注意区分定制化和易移......
  • 操作符详解(完)
    在前面的文章里,已经对基本上大概所有的操作符都进行了讲解,本章主要针对之前未曾讲解过的,以及一些博主认为很重要的进行讲解。移位操作符移位操作符一共有两个,一个是左移操作......
  • 10.4 汇编语言的语法是“操作码+操作数”
     在汇编语言中,1行表示对CPU的一个指令。汇编语言指令的语法结构是操作码+操作数(或只有操作码没有操作数的指令)。 能够使用任何形式的操作码,是由CPU的种类决定的。 ......
  • VUE简介/插值/属性/文本/函数指令/if/for操作
    VUE简介/插值/属性/文本/函数指令前端发展史1.前后端一体的,HTML(5)、CSS(3)、JavaScript(ES5、ES6):编写一个个的页面->给后端(PHP、Python、Go、Java)->后端嵌入模板......