Fragment 源码解析(二):FragmentManager 生命周期

2,106 阅读7分钟

Fragment源码解析(一): Activity与 FragmentManager是如何关联的呢?

上一篇文章我们从源码的角度分析了 FragmentManager 是如何与 Activity 关联的, 这篇文章将继续从源码的角度出发, 分析一下 FragmentManager 的生命周期.

相信有很多人看到这篇博客的标题时肯定会有疑问:FragmentManager 的生命周期? FragmentManager也有生命周期吗?是不是标题写错了?

其实并没有写错, 这篇文章要分析的就是 FragmentManager 的生命周期!大家平时在谈论 Fragment 的时候, 讨论的都是 Fragment 的生命周期, 却忽略了 FragmentManager 的问题. 直观感受是Activity 的各个生命周期去推动着 Fragment 执行它自己的生命周期, 实际情况是这样的吗? 下面我们从源码当中看看随着 Activity 的生命周期的变化, FragmentManager 内部是如何跟着变化的..

为了能让大家跟上思路, 先直接上图:

这里涉及到是三个对象, activity, FragmentManager 以及 Fragment,今天我们只分析 FragmentMananger 的生命周期.

上一篇文章中我们分析了 FragmentManager 的创建是在 activity 创建的时候:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        activity = mInstrumentation.newActivity(cl,
            component.getClassName(), r.intent);
        ...
}

在newActivity()方法内部会创建 activity对象, 此时 FragmentManager 对象也会被创建, 接着向下看 performLaunchActivity()方法发现, 该方法在创建了 activity 后, 调用了activity的 attach()方法:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        activity = mInstrumentation.newActivity(cl,
            component.getClassName(), r.intent);
        ...
        activity.attach(...)
        ...
}

看到没, 当 activity 被创建以后, 紧接着就调用了 activity 的 attach()方法, 点击进入 attach()方法:

final void attach() {
    ....
    mFragments.attachHost(null /*parent*/);
    ...
}

在 attach()方法的第一行就调用了 mFragments的 attachHost()方法, 还记得 mFragments 是什么吗? 它是在 activity 内部定义的一个变量:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

FragmentController内部没有做什么实质性的操作, 它就是一个中间层, 内部实现如下:

public void attachHost(Fragment parent) {
        mHost.mFragmentManager.attachController(
                mHost, mHost /*container*/, parent);
    }

这样就调用到了FragmentManager 的 attachController()方法, 到这里我们终于看到了 FragmentManager 的身影,进去看一下该方法做了什么(这里要查看 FragmentManagerImpl类):

public void attachController(@NonNull FragmentHostCallback host,
            @NonNull FragmentContainer container, @Nullable final Fragment parent) {
        if (mHost != null) throw new IllegalStateException("Already attached");
        mHost = host;
        mContainer = container;
        mParent = parent;
        ...
}

在方法中,除了赋值以外,并没有做其他的操作, 这里的 mHost 就是 activity 内部类 HostCallback, mContainer 就是 activity 直接操作的没有做什么实质工作的 FragmentContainer, mParent 指的是要依附的Fragment, 当前的过程是 activity 驱动的, 所以不存在 fragment, 该值为 null.

到目前为止过程是这样的:

1.启动一个 activity 
2.activity 初始化, FragmentManager 被创建
3.调用 activity 的 attach()方法
4.activity 通过 FragmentContainer 调用了 FragmentManager 的 attachController()方法, 将 FragmentHostCallback 和 FragmentContainer 对象传入 FragmentManager 中.

activity 的 attach()方法调用后, 接下来就应该调用 activity 的 onCreate()方法了, 还是 performLaunchActivity()方法内:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        activity = mInstrumentation.newActivity(cl,
            component.getClassName(), r.intent);
        ...
        activity.attach(...)
        ...
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
}

可以看到, 接下里就会调用 mInstrumentation 的 callActivityOnCreate()方法, 该方法中会调用 activity 的 performCreate()方法:

public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
}

该方法中关键方法就是下面这段:

activity.performCreate(icicle, persistentState);

继续..

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ...
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ...
        mFragments.dispatchActivityCreated();
        ...
    }

哇, 终于看到了熟悉的 mFragments 了, 但是先别着急, mFragments 的上面还有 onCreate()方法, 这个不就是 activity 的 onCreate()方法吗? 在 onCreate()方法内部会不会有有用的信息呢? 查看 onCreate()方法, 你会发现下面的代码:

mFragments.dispatchCreate();

这样逻辑就应该是这样的, 在 activity 执行 onCreate()方法的时候, mFragments 先调用了 dispatchCreate()方法, 再调用了 dispatchActivityCreated()方法, 我们同时看一下这两个方法:

public void dispatchCreate() {
    mHost.mFragmentManager.dispatchCreate();
}
public void dispatchActivityCreated() {
    mHost.mFragmentManager.dispatchActivityCreated();
}

在FragmentManager 中调用情况如下:

public void dispatchCreate() {
    mStateSaved = false;
    mStopped = false;
    dispatchStateChange(Fragment.CREATED);
}
public void dispatchActivityCreated() {
    mStateSaved = false;
    mStopped = false;
    dispatchStateChange(Fragment.ACTIVITY_CREATED);
}

咦, 发现了Fragment 的静态变量, 点击进去看一下 Fragment 这个变量的值,发现他并不是一个人:

static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3;          // Created and started, not resumed.
static final int RESUMED = 4;          // Created started and resumed.

这几个是 Fragment 的五个状态, 但是到目前为止我们没有涉及到任何 Fragment, 只有 FragmentManager, 但是接下来调用的两个方法竟然接受 Fragment 的状态值, 这又是为什么呢? 这两个方法调用的是同一个方法,即dispatchStateChange(), 只不过传入的静态值不一样,接下来我们点击进入该方法看一下:

private void dispatchStateChange(int nextState) {
    try {
        mExecutingActions = true;
        moveToState(nextState, false);
    } finally {
        mExecutingActions = false;
        }
        execPendingActions();
    }

该方法中并没有发现state值的操作, 而是将 state 值传入到另一个方法 moveToState()方法中,在该方法中发现了一段重要的代码:

void moveToState(int newState, boolean always) {
    ...
    mCurState = newState;
    ...
}

该方法中将传进来的 state 值赋值给了 变量 mCurState, 从字面意思就能看出来, 该值的意思是当前的状态, 那么这个状态时谁的状态呢? 该变量定义在 FragmentManager(FragmentManagerImpl) 中, 那当然指的就是 FragmentManager 的状态了, 并且他有一个初始化的值:

int mCurState = Fragment.INITIALIZING;

这里有个疑问, 既然是 FragmentManager的状态值, 那么为什么这些静态变量要定义在 Fragment 中呢?其实就在 Fragment 定义的这几个状态值的下面, 还定义一个变量:

int mState = INITIALIZING;

可以看到 Fragment 同样也定义了一个状态值, 并且 Fragment 状态值的初始值跟 FragmentManager 的一样! 看到这里想必大家应该明白了, Fragment 是有生命周期的, 且不同的生命周期阶段mState 的值是不一样的, 同样的 FragmentManage 也是有生命周期的, 它的内部同样也定义了一个 state, 这个状态值就是 mCurState!
目前为止 activity 的生命周期执行了 onAttach()和 onCreate()方法两个, onAttach()方法并没有改变 FragmentManager 的状态值, 而 onCreate()方法的执行改变了 FragmentManager 的状态值 , 并且是改变了两次! 我们可以用下面的图来总结一下这个过程:

FragmentManager 最初的状态时 INITIALIZING 的, 当 activity 执行了onCreate()方法后状态显示变成 CREATED, 再变成 ACTIVITY_CREATED状态.
同样的道理, 当 activity 执行其他的生命周期方法时, FragmentManager 的状态(生命周期)同样随之改变, 流程都是一样的:

1.activity 执行生命周期
2.activity 调用 FragmentController 的 dispatchxxx()方法
3.FragmentController 调用FragmentManagerImpl 的 dispatchxxx()方法

感兴趣的可以自己去看一下, 其实都不用去看 activity 的方法, 直接去看 FragmentController 的方法就可以了, 里面都定义了一些 dispachxxx()方法.
但是这里有一个疑问, 还记得我们 Fragment 里面定义的几个状态吗:

static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3;          // Created and started, not resumed.
static final int RESUMED = 4;          // Created started and resumed.

这里面定义了五个状态, 第一个状态是初始状态, 这样就剩下了四个状态, 这样就意味着 FragmentManager的生命周期只会有五个, 但是问题是 activity 的生命周期可不止五个哇! 并且 FragmentManager 的生命周期都是跟随 Activity 变化的, 这样该如何对应上呢??

其实当去查看其他源码时你会发现, FragmentManager 的生命周期确实是只有这五个, 只不过activity执行 onResume()之后的生命周期时, FragmentManager 的状态开始从 RESUMED向前执行, 就像开篇那张图片展示的那样, 我将 Fragment 相关的去掉会更直观一点:

至此, FragmentManager 生命周期就全部解析完了. 不知道大家发现没有, 我们这一个系列说的是从源码角度分析 Fragment 的, 但是到目前为止并没有涉及到任何Fragment的内容, 接下来的文章就会从源码的角度去分析 Fragment, 敬请期待!