Fragivity中对Fragment生命周期的优化处理

在这里插入图片描述

Fragivity是一个基于Fragment打造的单Activity框架。

开发者在使用同类框架时,往往都很关心Fragment的Lifecycle。Fragivity在这方面做了不少优化,解决了一些Navigation等其他框架中的痛点。

我们主要关心以下几个case中的生命周期表现:

  • 页面跳转/返回
  • 熄亮屏
  • Configurations Change(屏幕旋转等)

1. 页面跳转/返回


表现

当从FirstFragment启动SecondFragment时:

SecondFragment => onCreate
SecondFragment => onViewCreated
SecondFragment => onActivityCreated
SecondFragment => onStart
SecondFragment => onResume
FirstFragment => onPause
FirstFragment => onStop

  • SecondFragment 进入创建流程;
  • FirstFragment退出前台,但是不走onDestroyView,因为返回时不需要重建视图

当从SecondFragment返回FirstFragment时:

SecondFragment => onPause
SecondFragment => onStop
SecondFragment => onDestroyView
SecondFragment => onDestroy
FirstFragment => onStart
FirstFragment => onResume

  • SecondFragment 进入销毁流程
  • FirstFragment返回到前台,但是没有重新onCreateView

相对于Navigation等其他框架的改善在于避免了返回时重新创建视图,与Activity的行为一致。

实现原理

Navigation由于使用replace方式切换Fragment,所以在回退时需要重新onCreateView。Fragivity使用add替代replace,避免了回退时的Fragment重建。

这样处理会带来一个问题:切到“后台”的Fragment视觉上被遮挡,但实质上仍然是attach状态,其生命周期默认应该跟随Activity一致,所以此处需要监听BackStack的变化,当栈顶发生变化时(即有新的Fragment入栈),需要对进入“后台”的Fragment进行performStop操作;反之进入“前台”时也同样处理。


2. 熄亮屏


表现

当前回退栈里有FirstFragment、SecondFragment两个页面,SecondFragment处于栈顶。此时熄灭/点亮屏幕:

SecondFragment => onPause
SecondFragment => onStop

SecondFragment => onStart
SecondFragment => onResume

  • SecondFragment与宿主Activity的Lifecycle一致
  • FirstFragment虽然也在栈中但是由于身处后台,所以不受影响

实现原理

Fragivity使用add方式切换Fragment,即使Fragment处于“后台”,由于是attached状态,当点亮屏幕时,默认会随Activity进行onStart、onResume。这显然不是我们希望的。

Fragivity为进入回退栈的所有的Fragment都封装了一个代理ReportFragment
在这里插入图片描述

有时从系统层面直接对Fragment做hook不太方便,借助ReportFragment可以降低处理成本,有机会对被代理对象做一些手脚。

当点亮屏幕时,借助ReportFragment拦截系统分发给“后台”Fragment的stateChange,实现其不响应Activity生命周期的需求。


3. Configurations Change(横竖屏等)


表现

当前回退栈里有FirstFragment、SecondFragment两个页面,SecondFragment处于栈顶。此时旋转屏幕:

SecondFragment => onPause
SecondFragment => onStop
SecondFragment => onDestroyView
FirstFragment => onDestroyView
SecondFragment => onViewCreated
SecondFragment => onActivityCreated
SecondFragment => onStart
SecondFragment => onResume

  • 配置变化会触发销毁重建。销毁流程中,栈内所有Fragment推进到onDestroyView,Fragment的retainInstance=true,所以不执行onDestroy。处于“后台”的FirstFragment由于已经执行过onStop,所以只执行onDestroyView

Fragment只能使用默认构造函数重建,所以Fragivity会为入栈的所有Fragment设置retainInstance = true,这样可以使用自定义构造函数创建Fragment且不用担心恢复重建的问题

  • 重建流程中,SecondFragment正常重建,但是FirstFragment由于处于“后台”为了提高性能,不进行重建,只有当返回“前台”时

SecondFragment旋转屏幕后,再回退到FirstFragment:

SecondFragment => onPause
SecondFragment => onStop
SecondFragment => onDestroyView
SecondFragment => onDestroy
FirstFragment => onViewCreated
FirstFragment => onActivityCreated
FirstFragment => onStart
FirstFragment => onResume

  • SecondFragment出栈销毁
  • FirstFragment进入“前台”,进入创建流程

当配置变化引起销毁重建时,只对前台Fragment第一时间进行重建,对于后台Fragment暂不重建,当栈内的Fragment数量很多时也不会影响重建性能。

实现原理

同样需要借助ReportFragment做一些拦截:将是否处于“后台”的状态存入ViewModel,当恢复重建时识别其“后台”身份,对dispatchResume进行拦截。


FIN


以上就是Fragivity中的Lifecycle处理思路,希望能为其他类似的需求提供参考。

猜你喜欢

转载自blog.csdn.net/vitaviva/article/details/113486036