Fragment的后台任务栈--BackStack


我们知道Activity的页面组织形式有“任务栈”的概念,它管理着Activity页面的进出规则。类似的,Fragment作为一种轻量级的页面,也有Fragment后台栈的概念。本文将介绍Fragment后台任务栈(BackStack)的相关知识。

1. 任务栈的概念

首先,“栈”是数据结构中一种盛放数据的模型,特点是“先进后出(FILO,First in last out)”。好比是一个瓶子,数据只能从瓶口放入,从瓶口取出,并且每个数据都是盖在前一个之上的。这就意味着,要想取出下面的,就得先把上面的取出来。因此是先进后出。
类比到我们的Android页面,也存在这样一个“页面栈”,每跳转一个新页面,就意味着该页面被放入“页面栈”中,盖着最上面。用户能看到的只有当前栈顶的页面,当按下返回键时,栈顶页面被弹出,下一个页面处于栈顶,呈现在用户面前。

2. Fragment后台栈

从前文中我们已经了解到如何添加Fragment,但并没有把它加入BackStack。当然,并不是一定要加入BackStack,这取决于我们的需求场景。那么是否加入BackStack有什么不同呢?

添加Fragment,未加入BackStack

下面代码是添加Fragment的简单步骤,我们通过fragmentTransaction.add(R.id.fragment_container, fragmentA).commit();将FragmentA添加到R.id.fragment_container这个容器上。

// 1.准备FragmentManager 和 FragmentTransaction
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 2.创建Fragment
FragmentA fragmentA = new FragmentA();
// 3.添加Fragment (不要忘记最后的commit)
fragmentTransaction.add(R.id.fragment_container, fragmentA).commit();
// 或者:fragmentTransaction.add(R.id.fragment_container, FragmentA.class, null).commit();

同样的方式,我门再添加FragmentB、FragmentC到R.id.fragment_container这个容器上。此时,该容器上被添加了三个Fragment,那么它们是怎样的存在形式呢?

  • 页面“穿透”
    直观感觉是,三个Fragment依次覆盖,从下到上为FragmentA、FragmentB、FragmentC,用户当前看到的是FragmentC,似乎和“栈”一样。但这只是表象。的确,三者是这样的关系,但和栈不同的是,三个页面是“穿透的”。也就是用户点击上面的FragmentC的空白处(没有按钮等View),会透传点击到下面的FragmentB。因为它们并不是用“栈”盛放的,而是像普通View一样添加进去而已,类似FrameLayout里添加View,可以想象到吧。

  • 返回键退出所有Fragment
    虽然被添加到Fragment也是一个盖着一个,但整体来看还是Activity里的一个容器页面,当点返回键的时候,作用到整个Activity上,Activity销毁退出,它上面所有的Fragment也都销毁退出了。

添加Fragment,并加入BackStack

在添加Fragment的时候,我们可以通过addToBackStack("myBackStack")将其同时加入到后台栈里,“myBackStack”是本次添加对应的栈帧名,可以理解为在栈中的一个标记。如下面代码所示:

   getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_container, FragmentA.class, null)
                .addToBackStack("myBackStack")
                .setReorderingAllowed(true)
                .commit();

同样的方式再添加FragmentB、FragmentC到R.id.fragment_container里。此时它们的存在形式上怎样的呢?

  • 页面“穿透”
    Fragment也是一个盖一个的添加到容器上,同样有页面点击穿透的现象。

  • 返回键退出栈顶Fragment
    这就是Fragment后台栈的主要作用之一。Fragment不仅被添加到容器上,还被添加到BackStack里,可以响应返回键,从而依次退出栈顶的Fragment,像Activity的出栈一样。
    应用到当前例子就是:按返回键,FragmentC、FragmentB、FragmentA依次退出,再按返回才是退出Activity。

3. BackStack暂存与恢复Fragment(save/restore)

saveBackStack

BackStack的另一个作用是,可以暂存一些Fragment,将其保存在一个看不见的地方。页面表现是这些Fragment被弹出了。
另外,值得注意的一点是,它会弹出指定stack名及其以上的Fragment

FragmentManager fragmentManager = getSupportFragmentManager();
// 弹出 myBackStack及其以上所有的Fragment
fragmentManager.saveBackStack("myBackStack");

上面代码,就是把最下面的栈帧名为“myBackStack”的Fragment及其以上所有的Fragment全部弹出,暂时保存起来了。
这个过程,被弹出(暂存)的Fragment生命周期会发生变化,依次执行生命周期方法----onPause-----onStop------onDestroyView----onDestroy—

restoreBackStack

既然有暂存,就会有对应的恢复。

FragmentManager fragmentManager = getSupportFragmentManager();
// 恢复 myBackStack1及其以上所有的Fragment
fragmentManager.restoreBackStack("myBackStack1");

上面代码,就是把之前弹出(暂存)的那些Fragment又重新添加,并加入BackStack,栈帧的名字也和之前一样。

4. Remove方法不会将BackStack里的Fragment移除

前文我们介绍了Fragment的增删替查等操作。需要注意的一点是:对于加入到BackStack里的Fragment,只有通过返回键或者saveBackStack方法才能移除。普通的remove操作,只是把Fragment从容器View中移除,BackStack里仍然有该Fragment

也就意味着,假如你已经调用remove方法移除了当前Fragment,页面表现确实是该页面消失了。但此时你按返回键,BackStack里的Fragment仍能得到响应而退出,而Activity没有得到响应,给你的感觉是,页面什么也没变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

子林Android

感谢老板,老板大气!

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

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

打赏作者

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

抵扣说明:

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

余额充值