FragmentManager与FragmentTransaction

1. FragmentManager简介

FragmentManager,顾名思义是负责管理Fragment的管理类,可以对Fragment进行添加、移除、替换等操作。并且,Fragment也有和Activity类似的任务栈。Fragment可被添加到栈中,也可以出栈。

2. FragmentManager的获取

2.1 从Activity中获取FragmentManager

从前面的章节我们了解到,Fragment是依附在Activity上的子页面。那么负责管理这些子页面的FragmentManager自然可从Activity上获取了。只不过这种Activity比较特殊,是一种FragmentActivity。

  • ApppCompatActivity、FragmentActivity、Activity三者的继承关系是: ApppCompatActivity继承自FragmentActivity,FragmentActivity继承自Activity
    因此,FragmentActivity或者是继承自FragmentActivity的子类(比如,ApppCompatActivity)都可以获得FragmentManager。获取方法是:getSupportFragmentManager()。从support可以看出,这里获取的是具有兼容性的Fragment,也就是Android Support或者AndroidX包里面的Fragment。
  • 注意,不要用老旧的android.app.fragment, getFragmentManager() ,已不推荐使用。

2.2 从Fragment上获取FragmentManager

Fragment除了依附在Activity上,也可以依附在别Fragmet上。这时被依附的Fragment就是父Fragment,依附的Fragment就是子Fragment。
那么管理子Fragment的FragmentManager自然可以从其父Fragment里获取。方法是: getChildFragmentManager()。也好理解,管理子Fragment嘛,自然是getChildFragmentManager。
上面是一个Fragment获取其子Fragment的管理类( getChildFragmentManager()),而要想获取管理自身的管理类,可以通过getParentFragmentManager()方法实现。

Fragment与其持有者(Activity或父Fragment),还有FragmentManager的对应关系可用下图表示:
Fragment与其持有者(Activity或父Fragment),还有FragmentManager的对应关系

3. FragmentTransaction简介

FragmentManager是Fragment的管理者,但它还需要一个助手帮它完成Fragment的add、replace等操作。这个助手就是FragmentTransaction。

对Fragment的添加、替换等操作可能会有多个。比如先移除当前FragmentA,再添加FragmentB,这样两个操作通常就被打包一次Transaction,统一提交(commit)。比如下面的代码:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
	.remove(fragmentA)
	.add(R.id.fragment_container, FragmentB.class,null)
    .setReorderingAllowed(true)
    .addToBackStack("name") // name can be null
    .commit();
  • Transaction,是事务的意思,原本是数据库中的概念。引申到这里,可理解为把多个操作打包为整体,统一提交。如果其中某个操作失败了,那么整个操作全部恢复到操作之前。这样可以保证操作的完整性
  • 举个例子,A向B转账100元的操作可简化为以下几步:1.A的账户钱数减100; 2. B的账户加100。假如操作1执行完,操作2执行失败了,那么整个转账操作应该认为是失败的,应该回退到转账之前。这时候“事务”的操作就发挥作用了。根据“事务”的概念,1和2应该是一个整体,2失败了,那么所有操作恢复到操作之前。因此,“操作1. A的账户钱数减100”,就会回退到之前,即再加100恢复到原数目,从而保证了数据的完整性。

4. FragmentTransaction的获取

从上面代码可以看出FragmentTransaction是FragmentManager的助手,自然会通过FragmentManager获得。如下代码:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()

5. 二者结合的典型用法

了解了FragmentManager以及FragmentTransaction后,我们来看二者结合后常见的操作,比如将一个Fragment添加到某个FragmentContainer上。

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null)
    .setReorderingAllowed(true)
    .addToBackStack("name") // name can be null
    .commit();

这里值得注意的有以下几点:

  1. 使用ExampleFragment.class而不是某个ExampleFragment对象,原因上节已经解释过
  2. 添加setReorderingAllowed(true),原因仍参见上节
  3. addToBackStack(“name”),将本次操作整体添加到一个后台栈里。当用户点击返回键时,就能依次弹出,当弹到栈为空,时再按返回键,事件就会传递到所在Activity,执行其任务栈的回退。
  4. 如果不加addToBackStack,当你移除一个Fragment后,该Fragment会被销毁,无法再跳到该Fragment。而加了addToBackStack后,Fragment被移除后,该Fragment只是切换到了Stop状态,仍然有机会再跳转到该Fragment。

6. 获取某个已添加的Fragment

Fragment被添加后,有两种方式获取已添加的Fragment对象。

  • findFragmentById
  • findFragmentByTag

6.1 findFragmentById

通过被添加到的容器的id获取,该容器上当前的Fragment实例。
代码举例如下:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null)
    .setReorderingAllowed(true)
    .addToBackStack(null)
    .commit();

ExampleFragment fragment =
        (ExampleFragment) fragmentManager.findFragmentById(R.id.fragment_container);

6.2 findFragmentByTag

Fragment添加的时候,可以为其加上一个Tag作为标签。这样后面就可以根据该标签找到它了。
代码举例如下:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null, "tag")
    .setReorderingAllowed(true)
    .addToBackStack(null)
    .commit();

ExampleFragment fragment = (ExampleFragment) fragmentManager.findFragmentByTag("tag");

7. 支持多个Fragment后台栈

有时我们需要同时操作多个Fragment栈。比如,底部导航菜单+多个Fragment页面。通过FragmentManager,我们可以暂存某个栈,显示另一个栈。对应的方法分别是saveBackStack()restoreBackStack()
代码举例如下:
首先,将Fragment添加到栈

supportFragmentManager.beginTransaction()
  .replace(R.id.fragment_container, ExampleFragment.class, null)
  .setReorderingAllowed(true)
  .addToBackStack("replacement")
  .commit();

注意,这里的setReorderingAllowed(true)addToBackStack 是必须的。这样才能使用saveBackStack和restoreBackStack。

接着,暂存Fragment栈。被暂存(弹出)的Fragment会执行到onDestory方法,也就是会销毁。

// 弹出 replacement及其以上所有的Fragment
supportFragmentManager.saveBackStack("replacement");

然后,恢复Fragment栈。恢复Fragment时,会重新创建Fragment。

// 恢复 replacement及其以上所有的Fragment
supportFragmentManager.restoreBackStack("replacement");

注意,这里的saveBackStack(“replacement”)restoreBackStack("replacement")会将"replacement"这次操作以上所有的Fragment移出。

8. 总结

本章节介绍了FragmentManager与FragmentTransaction的概念和用法,以及如何获取某个已添加的Fragment,还涉及了对Fragment后台栈的理解。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子林Android

感谢老板,老板大气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值