Fragment生命周期注意事项

相比Activity,Fragment生命周期更为繁琐和复杂,主要是因为Fragment既继承了Activity的生命周期,也有自有的回调方法。某些场景下,必须几个回调方法结合使用才能解决问题

初始场景

APP首页是由5个tab组成,每个tab都是由Fragment实现的。分别为A B C D E。一个产品需求是,在A展示的时候,刷新某个接口请求。

需求分析

FragmentA可见性变化,分为两种情况:

  1. 当A从hide变为show的时候;
  2. 当A在show的情况下,Activity resume的时候;
    那么此时我们需要处理的回调方法主要有两个:
  3. onHiddenChanged.此方法在Fragment从hide状态变为show状态的时候调用。需要注意的是,在Fragment第一次调用show方法的时候,此回调不会执行。
  4. onResume. 此方法是Fragment从Activity处获得的,实际上是Activity的回调。这里需要注意的是,即使Fragment已经隐藏了,在Activity resume的时候,仍然会回调此方法,所以需要在此处添加对Fragment可见性的判断。防止不必要的流量和性能损失。
    这样处理后,初始场景的需求就完美解决了。

复杂场景

最开始,我们是使用下方的Tab,控制上方Fragment的显隐,交互相对简单。产品调研后提出,要类似微信一样,加入滑动切换功能。这个时候,就需要加入ViewPager进行嵌套了。这个时候的处理方式又有了什么样的变化呢?

变化分析

最开始我们只涉及到onResume和onHiddenChanged两个回调方法,但是加入viewpager后,viewpager默认会缓存Fragment,导致我们在浏览第一个Fragment的时候,第二个Fragment已经被实例化了。
这个时候我们需要特别注意一个方法的调用:setUserVisibleHint。这个方法并不是由Fragment或FragmentManagerImpl等框架代码调用,而是由FragmentPagerAdapter调用的。这个方法设计的初衷是用于标识是否对用户可见。代码中默认设置为true了。外部可以根据实际情况进行修改。
在viewpager中进行滑动切换的时候,onResume和onHiddenChanged方法都不会被调用,只有setUserVisibleHint方法会调用。现在有大量关于Fragment懒加载的文章,都是结合此方法来实现的。这里就不再赘述了。

综上,对于Fragment可见的判断需要在三个地方进行。

  1. setOnUserVisibleHint。同时需要判断Fragment是否已经创建,是否已经添加到Parent上。(这里和懒加载的判断不一样,懒加载是另外的逻辑)
  2. onHiddenChanged。
  3. onResume。同时需要判断是否添加到Parent上了,userVisibleHint是否为true,isHidden情况。

更复杂的场景

以上场景属于比较复杂,但是还有更复杂的情况。很多时候,Fragment不是直接由Activity来管理的,而是由Fragment getFragmentManager来管理的。这种嵌套的情况,判断Fragment是否可见更加复杂,不但需要判断自身的可见性,还需要结合Parent的可见性。在开发的时候,尤其需要注意。