前言

Fragment对于 Android 开发人员来说一点都不陌生,由于差点儿不论什么一款 app 都大量使用 Fragment,所以 Fragment 的生命周期相信对于大家来说应该都非常清晰。但绝大部分人对于其生命周期都停留在表象,知道一个 Fragment 从创建到运行再到销毁所要经过的过程。但却不知道内部怎样实现。或许有人会这样说,给你一辆摩托车,你仅仅要会骑即可。不须要拆开来看它内部的组成结构;对于这种问题,我仅仅想说,编程不仅学开车,还要学会造车,而且通过了解实现原理。能够让我们更加清晰的理解 Fragment的生命周期。往往我们通过理解来掌握的东西,是不易忘记的。

Fragment 生命周期流程图

好了。来看以下流程图来回想一下 Fragment 的生命周期

分析

要分析 Fragment 的生命周期,离不开这四个类

FragmentActivity.java
FragmentManager.java
Fragment.java
BackStackRecord.java

启动 app 首先启动的是FragmentActivity。我们就从它開始看起。在 onCreate()方法中

    @Override
protected void onCreate(Bundle savedInstanceState) {
//Fragment管理类绑定 Activity
mFragments.attachActivity(this, mContainer, null);
// Old versions of the platform didn't do this!
if (getLayoutInflater().getFactory() == null) {
getLayoutInflater().setFactory(this);
} super.onCreate(savedInstanceState); NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
if (nc != null) {
mAllLoaderManagers = nc.loaders;
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}
mFragments.dispatchCreate();
}

这里的mFragments就是FragmentManager,onCreate 中主要做了两件事,一、把FragmentManager和 Activity绑定,二、 向 Fragment分发 OnCreate 方法mFragments.dispatchCreate();看到这里。不知道大家有没有疑问。这里就会运行 Fragment 的onAttach 和 onCreate 方法吗?答案显然是错误的。由于我们都知道我们在运行 add + commit的时候才会运行,那么这里的 attach 和 onCreate 做了什么事?进去看看

    public void attachActivity(FragmentActivity activity,
FragmentContainer container, Fragment parent) {
if (mActivity != null) throw new IllegalStateException("Already attached");
mActivity = activity;
mContainer = container;
mParent = parent;
}

以上代码,仅仅是对变量的赋值,所以不会触发 Fragment 中的方法。

    public void dispatchCreate() {
mStateSaved = false;
moveToState(Fragment.CREATED, false);
}

貌似触发了 Fragment 中的 onCreate方法,继续看看。

    void moveToState(int newState, int transit, int transitStyle, boolean always) {
//...省略部分代码
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
//...省略部分代码
}

这里有个一推断if (mActive != null),由于我们眼下还没有地方初始化它,所以这里显然不成立,所以 dispatchCreate 方法也没有触发Fragment 中的不论什么方法,可是这里有一个须要注意

mCurState = newState;

也就是说当前状态变成了 Fragment.CREATED

FragmentActivity 中的其它方法如 onStart、onResume 都跟 onCreate 方法一样。都没有触发 Fragment 中的方法,

但mCurState 确发生了改变,变成了最后一个状态的值—> Fragment.RESUMED;

此时 Activity 已经启动了, FragmentManager中的mCurState也已经是Fragment.RESUMED,我们都知道,当我们通过FragmentManager.beginTransaction().add().commit()这时才是正在启动一个 Fragment。通过跟踪代码,commit终于调用的代码例如以下

    public void run() {
//....省略非常多代码
while (op != null) {
switch (op.cmd) {
case OP_ADD: {
//add 会走这里
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
mManager.addFragment(f, false);
} break;
case OP_REPLACE: {
//...省略
} break;
case OP_REMOVE: {
//...省略
} break;
case OP_HIDE: {
//...省略
} break;
case OP_SHOW: {
//...省略
} break;
case OP_DETACH: {
//...省略
} break;
case OP_ATTACH: {
//...省略
} break;
default: {
//...省略
}
} op = op.next;
}
//最后会去改变状态,这里就是整个生命周期运行的关键代码
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true); if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}

上面代码非常长,省略了部分代码,仅显示关键代码,当我们在 add 和 commit 之后,Fragment 会运行mManager.addFragment(f, false);这种方法

        if (mAvailIndices == null || mAvailIndices.size() <= 0) {
if (mActive == null) {
mActive = new ArrayList<Fragment>();
}
f.setIndex(mActive.size(), mParent);
mActive.add(f); } else {
//...省略
}

我们在前面就已经讲过了这个if (mActive == null) ,它是在这里初始化的,所以当我们再次运行

moveToState(int newState, int transit, int transitStyle, boolean always)

的时候,这里是能够通过的,在 commit 之后就有这样一段代码

//最后会去改变状态,这里就是整个生命周期运行的关键代码
mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);

还记得mCurState的状态是什么吗?没错,就是我们前面分析的

mCurState = Fragment.RESUMED;

接下来就来看看 他是怎么moveToState

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
//...省略
if (f.mState < newState) {
//...省略
}
switch (f.mState) {
case Fragment.INITIALIZING:
//...省略
f.mCalled = false;
f.onAttach(mActivity);
//...省略
if (f.mParentFragment == null) {
mActivity.onAttachFragment(f);
} if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
f.mRetaining = false;
//...省略
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
container = (ViewGroup)mContainer.findViewById(f.mContainerId);
if (container == null && !f.mRestored) {
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ f.getResources().getResourceName(f.mContainerId)
+ ") for fragment " + f));
}
}
f.mContainer = container;
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
if (container != null) {
Animation anim = loadAnimation(f, transit, true,
transitionStyle);
if (anim != null) {
f.mView.startAnimation(anim);
}
container.addView(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
} f.performActivityCreated(f.mSavedFragmentState);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.mResumed = true;
f.performResume();
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.performPause();
f.mResumed = false;
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.performStop();
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (!mActivity.isFinishing() && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
f.performDestroyView();
if (f.mView != null && f.mContainer != null) {
Animation anim = null;
if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
anim = loadAnimation(f, transit, false,
transitionStyle);
}
if (anim != null) {
final Fragment fragment = f;
f.mAnimatingAway = f.mView;
f.mStateAfterAnimating = newState;
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
if (fragment.mAnimatingAway != null) {
fragment.mAnimatingAway = null;
moveToState(fragment, fragment.mStateAfterAnimating,
0, 0, false);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
f.mView.startAnimation(anim);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mInnerView = null;
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mDestroyed) {
if (f.mAnimatingAway != null) {
// The fragment's containing activity is
// being destroyed, but this fragment is
// currently animating away. Stop the
// animation right now -- it is not needed,
// and we can't wait any more on destroying
// the fragment.
View v = f.mAnimatingAway;
f.mAnimatingAway = null;
v.clearAnimation();
}
}
if (f.mAnimatingAway != null) {
// We are waiting for the fragment's view to finish
// animating away. Just make a note of the state
// the fragment now should move to once the animation
// is done.
f.mStateAfterAnimating = newState;
newState = Fragment.CREATED;
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
if (!f.mRetaining) {
f.performDestroy();
} f.mCalled = false;
f.onDetach();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDetach()");
}
if (!keepActive) {
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mActivity = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
}
}
}
}
}
} f.mState = newState;
}

代码非常多,也比較乱,这里我来简单分析一下,首先的知道这几种状态值的大小

    static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3; // Fully created, not started.
static final int STARTED = 4; // Created and started, not resumed.
static final int RESUMED = 5; // Created started and resumed.

如今是f.mState = Fragment.INITIALIZING。newState = RESUMED;

所以if (f.mState < newState)成立。特别注意在上面的代码中每个 case 语句后面都没有 break 关键字。

所以简化以后的代码是:

switch (f.mState) {
case Fragment.INITIALIZING:
f.onAttach(mActivity);
if (f.mParentFragment == null) {
mActivity.onAttachFragment(f);
}
f (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
} case Fragment.CREATED:
f.performCreateView(...)
f.onViewCreated(...)
f.performActivityCreated(...);
f.restoreViewState(...)
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
f.performStart();
case Fragment.STARTED:
f.performResume();

以上就是 Fragment 启动的全过程。看完启动。再来看看 Fragment 销毁的过程运行 remove().commit()之后会运行例如以下代码

 case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.removeFragment(f, transition, transitionStyle);
} break;
    public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
if (mAdded != null) {
mAdded.remove(fragment);
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
fragment.mRemoving = true;
moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
transition, transitionStyle, false);
}
}

能够看到最后一句。就是改变状态的调用,而且把newState 变为

Fragment.INITIALIZING或者Fragment.CREATED。如果当前 Fragment 在前台台运行。则为Fragment.INITIALIZING,我们如果当前值为Fragment.INITIALIZING。也就是当前运行的 Fragment 为我们所要移除的 Fragment。

由于if (f.mState < newState)不成立了,所以将会运行以下代码

else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
f.performPause();
case Fragment.STARTED:
f.performStop();
case Fragment.STOPPED:
f.performReallyStop();
case Fragment.ACTIVITY_CREATED:
saveFragmentViewState(f);
f.performDestroyView();
case Fragment.CREATED:
f.performDestroy();
f.onDetach();

千万不要被Fragment.CREATED这种命名给疑惑了,。尽管这里写的是Fragment.CREATED,但它运行的确实performDestroy()

总结:

细致分析就会发现整个生命周期事实上非常easy。简单来讲,就是 addView 和 removeView 的过程,仅仅是在当中增加了其它相似 Activity 的 onStart 等方法。

最后大家能够结合源代码再看一遍!

最新文章

  1. EF架构~为EF DbContext生成的实体添加注释(T5模板应用)
  2. 拿到腾讯实习offer的前后小事
  3. Linux下网络流量实时监控工具
  4. knockout 学习实例3 html
  5. Error generating Swagger server (Python Flask) from Swagger editor
  6. PHP学习(一)----变量及字符串
  7. synergy帮组提升办公效率
  8. Android开发——通过扫描二维码,打开或者下载Android应用
  9. uva 10313 Pay the Price(完全背包)
  10. Jenkins详细安装与构建部署使用教程(转)
  11. java算法 蓝桥杯 格子位置
  12. Spring AOP (二)
  13. Asp.net Image控件显示Bitmap生成图像
  14. pip 解决下载包速度慢的问题
  15. BugBugBugBugBugBugBugBugBugBugBugBugBugBugBug
  16. python day07作业
  17. 记录下安装ES过程中遇到的错误及解决
  18. 如何快速切换目录cd-linux
  19. Miller-Rabin素数测试算法(POJ1811Prime Test)
  20. 【大数据实战】Logstash采集-&gt;Kafka-&gt;ElasticSearch检索

热门文章

  1. 基于ubuntu 14.04 kvm虚拟化部署
  2. Web鼠标事件
  3. 使用 HTML5 Geolocation 构建基于地理位置的 Web 应用学习网站分享
  4. yum安装php7.2
  5. subprocess模块windows系统命令和linux系统命令
  6. python 列表(增删改查)
  7. LeetCode(90) Subsets II
  8. Java中TreeMap集合讲解
  9. 关于在一台主机上安装2个不同版本的Oracle服务端
  10. server 08 R2 NBL 报错:RPC 服务器在指定计算机上不可用