Android:Fragment生命周期(结合Activity的生命周期进行分析)


前言

本文记录笔者学习Fragment生命周期的心路历程

一、Fragment生命周期概述

在这一部分中,我们单纯以Fragment为观察对象,观察其生命周期
在Android开发平台的官方文档中,对Fragment的生命周期有如下的描述

尽管 Fragment 的生命周期与其拥有的活动相关联,但它在标准活动生命周期上也有自己的缺陷。它包括基本的活动生命周期方法,例如onResume(),但与活动交互和 UI 生成相关的方法也很重要。

Fragment(与用户交互)的一系列核心生命周期方法是:

  • onAttach(Activity)一旦Fragment与其活动相关联时调用。
  • onCreate(Bundle)调用以进行Fragment的初始创建。
  • onCreateView(LayoutInflater, ViewGroup, Bundle)创建并返回与片段关联的视图层次结构。
  • onActivityCreated(Bundle)告诉Fragment它的活动已经完成了它自己的Activity.onCreate().
  • onViewStateRestored(Bundle)告诉Fragment其视图层次结构的所有已保存状态都已恢复。
  • onStart()使片段对用户可见(基于其包含的活动正在启动)。
  • onResume()使片段开始与用户交互(基于其包含的活动被恢复)。

当一个Fragment不再被使用时,它会经历一系列反向回调:

  • onPause()片段不再与用户交互,因为它的活动被暂停或片段操作正在活动中修改它。
  • onStop()片段不再对用户可见,因为它的活动正在停止或片段操作正在活动中修改它。
  • onDestroyView()允许片段清理与其视图关联的资源。
  • onDestroy()调用以对片段的状态进行最终清理。
  • onDetach()在片段不再与其活动相关联之前立即调用。

放一张目前网上能找到的相对完整的生命周期如下
(相对完整),因为看过Google最新关于Fragment生命周期描述的uu就应该知道这篇生命周期的描述是不完整的,但是大体思路可以看看
在这里插入图片描述
这里给出如下案例进行阐述

启动

onAttach() -------> onCreate() [Fragment]-------> onCreateView() ------>onCreate()[Activity]->onActivityCreated->onViewCreated() -----> onStart()-------> onStart()(Activity) -------->onResume()(Activity) --------> onResume()
在这里插入图片描述

退出

onPause[Activity]->onPause[Fragment]->onStop[Activity]->onStop[Fragment]->onDestroy[Activity]->onDestroyView[Fragment]->onDestroy[Fragment]->onDetach[Fragment]
在这里插入图片描述

二、Fragment生命周期细述

1.onCreate(Bundle)

我们一般使用Fragment的无参构造函数,尽管我们可以通过自己定义书写Fragment的有参构造函数,但是这样做很容易导致不可预见的bug

当Activity被强制销毁,之后又被自动恢复的时候,Android系统会在这一过程中销毁并重新创建Fragment。
重新创建的机制是通过使用反射的方法来调用Fragment的无参构造函数来实现的。
因此,如果您是使用带参数的构造函数来实例化Fragment,并在其中将依赖的对象传递给它,那么在保存和恢复后,所有这些依赖的对象都将被设置为null。
因此,就像Activity一样,您需要使用onCreate(Bundle)方法作为构造函数的替代者。
Fragment中依赖对象的注入和初始化就发生在这里。

Fragment相关逻辑源码如下:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
 
    getInjector().inject(this); // inject dependencies
 
    if (savedInstanceState != null) {
    
    
        mWelcomeDialogHasAlreadyBeenShown = savedInstanceState.getBoolean(SAVED_STATE_WELCOME_DIALOG_SHOWN);
    }
     
    mActivityAsListener = (ActivityAsListener) requireActivity();
 
}

2.onCreateView(LayoutInflater, ViewGroup, Bundle)

看到这个方法,大多数人都会有疑惑的地方就是,为何Fragment不像Activity那样在onCreate()方法中初始化View呢,这里引用另外一位博主的解释

Activity在生命周期的转换过程中都只有同一个View hierarchy。 你在Activity的onCreate(Bundle)中初始化这个View hierarchy,然后它就会一直存在于Activity的整个生命周期,直到Activity被垃圾收集器回收为止。 您可以手动更改Activity的View hierarchy的组成,Android系统是不会为您做任何事情的。

然而,Fragment在其生命周期中可以存在有多个View hierarchy,由Android系统决定何时进行替换。
换句话说,你可以在程序运行的时候动态改变Fragment的View hierarchy,现在你应该清楚为什么不能在Fragment的onCreate(Bundle)中操作View了吧。 onCreate(Bundle)方法在Fragment被Attach到Activity后仅被调用一次,它无法支持Fragment的View hierarchy的动态化。

每次需要创建新的View hierarchy的时候,Android系统都会调用onCreateView(LayoutInflater, ViewGroup, Bundle)方法。 您的工作是创建View hierarchy并将其初始化为正确的状态,然后将它作为该方法的返回值,之后它就会被Android系统接管。

重写这个方法的主要原则是:Fragment中所有持有与View hierarchy相关的对象的引用的成员变量,必须在View onCreateView(LayoutInflater,ViewGroup,Bundle)中进行初始化。 换句话说,如果Fragment的成员变量持有View或者相关对象的引用,请确保在此方法中初始化这些成员变量,这非常重要。

换句话说,onCreateView()存在的意义就是使得Fragment可以动态改变其View hierarchy

3.onStart()

参照Activity的onStart()方法

4.onResume()

参照Activity

5.onPause()

参照Activity的onPause()方法

6.onStop()

这个方法的处理逻辑同样与Activity的onStop()方法相同。其基本的处理逻辑如下所示:

相关源码如下

@Override
public void onStop() {
    
    
    super.onStop();
 
    mSomeView.setOnClickListener(null);
 
    mFirstDependency.unregisterListener(this);
}

在这里需要完成两件事
1.取消Activity的相关注册
2.取消点击事件

之所以这样做,可以参照以下的解释

1:

如果在onPause()方法里调用mFirstDependency.unregisterListener(this),那么Activity将不会收到相关异步流程完成的通知。因此,它不能让用户感知到这一事件,从而完全违背了多窗口模式的设计初衷,这不是一种好的处理方式。
如果在onDestroy()方法里调用mFirstDependency.unregisterListener(this),这同样不是一种好的处理方式。
当应用被用户推到后台(例如,点击“home”按钮)时,Activity的onStop()将被调用,从而使得其返回到“已创建”状态,这个Activity可以在几天甚至几周的时间内保持这个状态。
如果这时候mFirstDependency产生了连续的事件流,那么在这几天甚至几周的时间里,Activity可以都处理这些事件,即使用户在这段时间内从未真正与它交互过。这将是对用户电池寿命的不负责任的浪费,而且在这种情况下,应用消耗的内存会逐渐增多,应用进程被OOM(Out
Of Memory)Killer杀死的可能性也会增大。
因此,在onPause()和onDestroy()里调用mFirstDependency.unregisterListener(this)都不是一种好的处理方式,您应该在onStop()中执行此操作。

2:
关于2的解释,主要是用户使用APP的连续性和解决Activity停止后事件仍然进行分发的结果

7.onDestroy():

不需要覆盖重写这个方法,这个方法完全只是相关资源的回收

8.onSaveInstanceState(Bundle):

此方法用于保存一些临时的状态,在这个方法里你位移需要做的就是将你想保存的状态存入Bundle数据结构中:

@Override
public void onSaveInstanceState(Bundle outState) {
    
    
    super.onSaveInstanceState(outState);
    outState.putBoolean(SAVED_STATE_WELCOME_DIALOG_SHOWN, mWelcomeDialogHasAlreadyBeenShown);
}

在这里,有个陷阱,如果你在这个方法执行完之后,提交Fragment事务,那么应用程序会抛出IllegalStateException异常而导致崩溃。
你需要知道的一点是onSaveInstanceState(Bundle)将在onStop()之前被调用。
好消息是,经过多年的努力,谷歌终于意识到了这个bug。 在新版本的Android中,==onStop()将在onSaveInstanceState(Bundle)==之前被调用。

总结

以上就是Fragment生命周期的分享和整理

猜你喜欢

转载自blog.csdn.net/qjyws/article/details/123256346