Fragment返回栈的手动管理

如何回到上一个Fragment

项目开中需要经常在不同的Fragment之间跳转,随时可能从一个Fragment页面跳到另一个Fragment页面。

这些页面的切换还是比较简单的,根据业务需求,相应地调用FragmentTransactionshow()、add()、hide()、replace()等方法,再提交事务就可以了。

当页面不是很多时,这种方法足以应付了。

但“返回上一页”这种需求随着页面入口的增加,就会越发使人抓狂了。

比如,E页面可能来自A、B、C、D中的任一个,当需要在E页面“返回上一页”时,要判断应该返回哪一个页面,一旦入口多了就让人很头疼了。

怎么解决这种困境?

想想Activity中“返回上一页”直接在当前页面finish()就可以了,多么轻松简单。

Android系统通过入栈出栈帮我们维护了Activity的返回栈,显示栈顶的Activity

Fragment有没有类似的实现呢?

还真有,不过Fragment的返回栈需要我们手动管理,很好玩的样子 O(∩_∩)O,让我们继续深入一探究竟!

手动管理返回栈

Fragment返回栈和Activity返回栈在结构上是一样的,都有入栈和出栈的动作。

所有继承FragmentActivityActivity都可以通过getSupportFragmentManager()方法获得FragmentManager,顾名思义,得到的是当前Activity中所有Fragment的管理者。

入栈

一次简单的入栈操作示例如下:

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.hide(from).show(to);
transaction.addToBackStack(to.getClass().getName());
transaction.commit();

通过调用FragmentTransactionaddToBackStack()方法,事务提交后就会将当前操作入栈。

如果紧接着进行出栈操作,就会将当前的操作反向进行。

出栈

出栈操作就更简单了,只需一行代码,不涉及事务:

fragmentManager.popBackStack();

这个方法是异步的,还有个同步方法popBackStackImmediate()

如果返回栈中数量不为0,则返回true,否则返回false

返回栈中个数
fragmentManager.getBackStackEntryCount();
获取返回栈中实例
fragmentManager.getBackStackEntryAt(0);

通过这些方法,再结合自身业务,我们就能手动维护一个Fragment返回栈,封装好相应的方法,灵活地入栈和出栈,碰到“返回上一页”这种需求时,只需一个简单的出栈操作就可以了!

现象总结

在手动维护Fragment返回栈时,发现:如果从A进入B入栈,在B中输入一些数据,返回A出栈,再进入B又入栈,之前在B中输入的数据还能恢复,让人不禁想看看这中间究竟经历了什么。

查看源码,可以看到出栈时只是将栈顶的Fragment移出了数组,并没有将其销毁。

所以当它再次入栈时,便能恢复之前的数据。

那么生命周期是怎样变化的呢?

经过实验,发现相关生命周期变化如下:

显示新页面时 hide 旧页面

A 到 B
	A生命周期无变化
	B( onAttach()  --> onViewStateRestored()--> onResume() )
	
B 返回 A
	A生命周期无变化
	B( onPause()  --> onDetach() )
	
A 再到 B
	A生命周期无变化
	B( onAttach()  --> onViewStateRestored()--> onResume() )
	
如果在B页面输入了数据,B返回A再到B,B中数据会恢复


显示新页面时 remove 旧页面

A 到 B
	A( onPause()  --> onDestroyView() )
    B( onAttach()  --> onViewStateRestored()--> onResume() )
    
B 返回 A
	A( onCreateView()  --> onViewStateRestored()--> onResume() )
 	B( onPause()  --> onDetach() )
 	
A 再到 B
	A( onPause()  --> onDestroyView() )
	B( onAttach()  --> onViewStateRestored()--> onResume() )
         
如果在B页面输入了数据,B返回A再到B,B中数据也会恢复

可以看到,再次进入B页面时,它的恢复生命周期会全部再走一遍,所有在恢复生命周期中的方法都会执行,视图需要重新生成。

如果第二次进入时不想再执行某些操作,可以在Fragment中加个标志位:

private boolean isFirstIn = true;

首次进入后执行isFirstIn = false;,之后再进入时isFirstIn将保持为false

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值