Fragment 生命周期源码分析

dependencies {
    val fragment_version = "1.3.4"

    // Java language implementation
    implementation("androidx.fragment:fragment:$fragment_version")
    // Kotlin
    implementation("androidx.fragment:fragment-ktx:$fragment_version")
    // Testing Fragments in Isolation
    debugImplementation("androidx.fragment:fragment-testing:$fragment_version")
}
  • Fragment 无论是单独使用还是配合Viewpager,对于Android开发来说非常熟悉了,但生命周期,一般就网上看到的一张图,想必大家也经常看到;


    Fragment lifecyclee
  • 那Fragment的生命周期在什么时候调用的,commit之后怎么走到生命周期的每一个方法,需要看源码才知道,本文就此分析。

1.supportFragmentManager

  • 只有使用 FragmentActivity 才有 supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.test_activity3_activity)
    if (savedInstanceState == null) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, TestActivity3Fragment.newInstance())
            .commitNow()
    }
}

1.1 getSupportFragmentManager

  • FragmentActivity里面的 mFragments 可不是Fragment数组哦,他是 FragmentController ,这个很重要,先记住他。
     /* FragmentActivity类 */
     
     //创建FragmentController 
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

    /**
     * Return the FragmentManager for interacting with fragments associated
     * with this activity.
     */
    @NonNull
    public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
    }

1.2 FragmentController类

  • new HostCallbacks() 传进去,再获取 SupportFragmentManager。
public class FragmentController {
    private final FragmentHostCallback<?> mHost;

    /**
     * Returns a {@link FragmentController}.
     */
    @NonNull
    public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
        return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
    }

    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }

    /**
     * 通过mHost获取FragmentManager
     * Returns a {@link FragmentManager} for this controller.
     */
    @NonNull
    public FragmentManager getSupportFragmentManager() {
        return mHost.mFragmentManager;
    }
}

1.3 FragmentHostCallback类

  • FragmentHostCallback 里获取 mFragmentManager
  • FragmentManagerImpl 继承FragmentManager,但什么都没做。
public abstract class FragmentHostCallback<E> extends FragmentContainer {
    @Nullable private final Activity mActivity;
    @NonNull private final Context mContext;
    @NonNull private final Handler mHandler;
    private final int mWindowAnimations;
    final FragmentManager mFragmentManager = new FragmentManagerImpl();
 }

//继承FragmentManager,但什么都没做
class FragmentManagerImpl extends FragmentManager {
}
  • 到此就获取一个fragmentManager。

2.beginTransaction

  • 每次处理Fragment的事务都是新建一个 BackStackRecord 回退栈 ,只能用一次。
    @NonNull
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

2.1 FragmentTransaction类

  • BackStackRecord 类是继承 抽象类FragmentTransaction,这里有非常重要的各个OP常量,还有内部类OP。
  • add,hide,remove等操作也是在这个类,他们都会封装进Op,用数组mOps 保存。
public abstract class FragmentTransaction {

    static final int OP_NULL = 0;
    static final int OP_ADD = 1;
    static final int OP_REPLACE = 2;
    static final int OP_REMOVE = 3;
    static final int OP_HIDE = 4;
    static final int OP_SHOW = 5;
    static final int OP_DETACH = 6;
    static final int OP_ATTACH = 7;
    static final int OP_SET_PRIMARY_NAV = 8;
    static final int OP_UNSET_PRIMARY_NAV = 9;
    static final int OP_SET_MAX_LIFECYCLE = 10;
    .
    .
    ArrayList<Op> mOps = new ArrayList<>();
}

2.2 Op类

  • Op这个类对于后面add,hide,remove等操作很重要。
static final class Op {
        int mCmd;
        Fragment mFragment;
        int mEnterAnim;
        int mExitAnim;
        int mPopEnterAnim;
        int mPopExitAnim;
        Lifecycle.State mOldMaxState;
        Lifecycle.State mCurrentMaxState;

        Op() {
        }
        .
        .
}

2.3 BackStackRecord类

  • 这个类就是真正执行提交事务的类,提交事务会把自己一起传给FragmentManager。
  • 还实现了 FragmentManager.OpGenerator 接口。
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
       final FragmentManager mManager;

    @Override
    public int commit() {
        return commitInternal(false);
    }

    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

    @Override
    public void commitNow() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, false);
    }

    @Override
    public void commitNowAllowingStateLoss() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, true);
    }
} 

3.add,hide,replace,remove

3.1 封装,addOp

  • 这里就分析一个replace,其他也是差不多的。
  • 这里做的就是把要替换的控件id,fragment,tag,操作对应的常量封装进Op类里。
/*FragmentTransaction*/

    /**
     * Calls {@link #replace(int, Fragment, String)} with a null tag.
     */
    @NonNull
    public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment) {
        return replace(containerViewId, fragment, null);
    }

    @NonNull
    public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment,
            @Nullable String tag)  {
        //判断数据有效性
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        }
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }


    void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
       .
       .
        //封装进Op
        addOp(new Op(opcmd, fragment));
    }

    /**
     * mOps 数组保持着这些操作
     * 把fragment进入退出动画一起加上,
     * 可以去setCustomAnimations方法看
     */
    void addOp(Op op) {
        mOps.add(op);
        op.mEnterAnim = mEnterAnim;
        op.mExitAnim = mExitAnim;
        op.mPopEnterAnim = mPopEnterAnim;
        op.mPopExitAnim = mPopExitAnim;
    }

4.commit

4.1 四种提交方式

  • 提交事务有四种,分别是,先不分析四种区别,不是本次重点。
1. commit()
2. commitAllowingStateLoss()
3. commitNow()
4. commitNowAllowingStateLoss()

4.2 提交事务

  • commit 只能操作一次,一次就把add,hide,replace等操作一起提交。
  • 提交事务其实就是把自己一起丢给FragmentManager执行。
    @Override
    public int commit() {
        return commitInternal(false);
    }
    
    int commitInternal(boolean allowStateLoss) {
        //只能commit一次,否则抛异常
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
            Log.v(TAG, "Commit: " + this);
            LogWriter logw = new LogWriter(TAG);
            PrintWriter pw = new PrintWriter(logw);
            dump("  ", pw);
            pw.close();
        }
        mCommitted = true;
        //是否加入回退栈
        if (mAddToBackStack) {
            // 放入回退栈标记的index
            mIndex = mManager.allocBackStackIndex();
        } else {
            mIndex = -1;
        }
        //操作入队
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

4.3 handler 发送

  • commit 是在主线程异步执行,就是通过handler执行。
 /*FragmentManager*/

    //保存操作
    private final ArrayList<OpGenerator> mPendingActions = new ArrayList<>();
 
    void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
    
        if (!allowStateLoss) {
            if (mHost == null) {
                if (mDestroyed) {
                    //FragmentManager 已经 销毁
                    throw new IllegalStateException("FragmentManager has been destroyed");
                } else {
                    //FragmentManager 还没绑定
                    throw new IllegalStateException("FragmentManager has not been attached to a "
                            + "host.");
                }
            }
            checkStateLoss();
        }
        //加锁
        synchronized (mPendingActions) {
            if (mHost == null) {
                //commitAllowingStateLoss会走这里
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            //加入到数组
            mPendingActions.add(action);
            //最终来到这里
            scheduleCommit();
        }
    }
  • 到这终于看到handler了,用post(Runnable)发送出去。
    void scheduleCommit() {
        synchronized (mPendingActions) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                //handler处理
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
                updateOnBackPressedCallbackEnabled();
            }
        }
    }

4.4 执行execPendingActions

    private Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions(true);
        }
    };

    /**
     * Only call from main thread!
     */
    boolean execPendingActions(boolean allowStateLoss) {
        ensureExecReady(allowStateLoss);

        boolean didSomething = false;
        //把事务放入临时变量
        while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
            mExecutingActions = true;
            try { 
                //优化整理事务           
                removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
            } finally {
                cleanupExec();
            }
            didSomething = true;
        }

        ...
        return didSomething;
    }

4.5 整理事务

  • removeRedundantOperationsAndExecute 有一大段注释,注释的意思就是说这方法删除冗余的操作,合并重复的操作,就是优化整理
  • 重点看到 record.expandOps 方法。
  • 拿出 Op 里面记录的操作,对不同操作处理,added增加或者移除,替换就是先移除再添加,具体可以看源码,这里就不贴全部了,有点多。
    /*FragmentManager*/
    
    /**
     * Remove redundant BackStackRecord operations and executes them. This method merges operations
     * of proximate records that allow reordering. See
    ...
     */
    private void removeRedundantOperationsAndExecute(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop) {
      ...
      
      executeOpsTogether(records, isRecordPop, startIndex, recordNum);
        ...


    private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
       //展开整理
       oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
    ...
}
    //展开整理
   Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
        for (int opNum = 0; opNum < mOps.size(); opNum++) {
            final Op op = mOps.get(opNum);
            switch (op.mCmd) {   
                //添加       
                case OP_ADD:
                case OP_ATTACH:
                    added.add(op.mFragment);
                    break;
                //移除
                case OP_REMOVE:
                case OP_DETACH: {
                    added.remove(op.mFragment);
                    if (op.mFragment == oldPrimaryNav) {
                        mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.mFragment));
                        opNum++;
                        oldPrimaryNav = null;
                    }
                }
                break;
                //替换
                case OP_REPLACE: {
                   ...
                }
                break;
                case OP_SET_PRIMARY_NAV: {
                   ...
                }
                break;
            }
        }
        return oldPrimaryNav;
    }

4.6 执行事务

  • 这里的FragmentManager.executeOps方法,再进入 BackStackRecord.executeOps方法,根据Op信息,处理再回到FragmentManager.moveToState方法。
    /*FragmentManager*/
    private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        
        ...
        executeOps(records, isRecordPop, startIndex, endIndex);
        ...
}

    private static void executeOps(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
       ..
       record.executeOps();

    
    /*BackStackRecord*/
    void executeOps() {
        final int numOps = mOps.size();
        for (int opNum = 0; opNum < numOps; opNum++) {
            final Op op = mOps.get(opNum);
            final Fragment f = op.mFragment;
           ...
            switch (op.mCmd) {
                case OP_ADD:
                    f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
                    mManager.setExitAnimationOrder(f, false);
                    mManager.addFragment(f);
                    break;
              .
              .
              .              
            }           
        }
        if (!mReorderingAllowed && !FragmentManager.USE_STATE_MANAGER) {
            // Added fragments are added at the end to comply with prior behavior.
            mManager.moveToState(mManager.mCurState, true);
        }
    }

4.7 状态改变

  • 首先我们能看到Fragment 的状态常量有哪些,其实有的版本,比如1.2.0只有5个,那这几个怎么够呢,好像生命周期不止这几个啊,就是创建时正着来,销毁时再反着来就行了。
public class Fragment implements ... {

    static final Object USE_DEFAULT_TRANSITION = new Object();

    static final int INITIALIZING = -1;          // Not yet attached.
    static final int ATTACHED = 0;               // Attached to the host.
    static final int CREATED = 1;                // Created.
    static final int VIEW_CREATED = 2;           // View Created.
    static final int AWAITING_EXIT_EFFECTS = 3;  // Downward state, awaiting exit effects
    static final int ACTIVITY_CREATED = 4;       // Fully created, not started.
    static final int STARTED = 5;                // Created and started, not resumed.
    static final int AWAITING_ENTER_EFFECTS = 6; // Upward state, awaiting enter effects
    static final int RESUMED = 7;                // Created started and resumed.

    int mState = INITIALIZING;
}
  • moveToState的代码是本次关键。
  • newState = Math.min(newState, fragmentStateManager.computeExpectedState()),这里跟官方提供的懒加载有关,可以限制fragment执行到哪个阶段,但现在先不管他。
  • if (f.mState <= newState) ,如果true , 可以看到后面的代码是创建流程,比如 Fragment.INITIALIZING ,ATTACHED,CREATED等等,否则就是销毁流程,这里就放一部分代码,可以自己去源码看看所有流程。
    void moveToState(int newState, boolean always) {
       ...
        moveFragmentToExpectedState(f);
       ...   
    }
    
    void moveFragmentToExpectedState(@NonNull Fragment f) {
        ...
        moveToState(f);
        ...
    }
    
    void moveToState(@NonNull Fragment f) {
        moveToState(f, mCurState);
    }

   void moveToState(@NonNull Fragment f, int newState) {
        //获取FragmentStateManager 
        FragmentStateManager fragmentStateManager = mFragmentStore.getFragmentStateManager(f.mWho);
        if (fragmentStateManager == null) {
          
            fragmentStateManager = new FragmentStateManager(mLifecycleCallbacksDispatcher,
                    mFragmentStore, f);
           
            fragmentStateManager.setFragmentManagerState(Fragment.CREATED);
        }
     
        if (f.mFromLayout && f.mInLayout && f.mState == Fragment.VIEW_CREATED) {
            newState = Math.max(newState, Fragment.VIEW_CREATED);
        }
        //这里跟官方提供的懒加载有关,可以限制fragment执行到哪个阶段
        newState = Math.min(newState, fragmentStateManager.computeExpectedState());
        if (f.mState <= newState) {
            // If we are moving to the same state, we do not need to give up on the animation.
            if (f.mState < newState && !mExitAnimationCancellationSignals.isEmpty()) {
                // The fragment is currently being animated...  but!  Now we
                // want to move our state back up.  Give up on waiting for the
                // animation and proceed from where we are.
                cancelExitAnimation(f);
            }
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    if (newState > Fragment.INITIALIZING) {
                        fragmentStateManager.attach();
                    }
                    // fall through
                case Fragment.ATTACHED:
                    if (newState > Fragment.ATTACHED) {
                        fragmentStateManager.create();
                    }
                    // fall through
                case Fragment.CREATED:
                    // We want to unconditionally run this anytime we do a moveToState that
                    // moves the Fragment above INITIALIZING, including cases such as when
                    // we move from CREATED => CREATED as part of the case fall through above.
                    if (newState > Fragment.INITIALIZING) {
                        fragmentStateManager.ensureInflatedView();
                    }

                    if (newState > Fragment.CREATED) {
                        fragmentStateManager.createView();
                    }
                    // fall through
                ...
                
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        fragmentStateManager.pause();
                    }
                    // fall through
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        fragmentStateManager.stop();
                    }
                    // fall through
                ...
            }
        }

        if (f.mState != newState) {
            if (isLoggingEnabled(Log.DEBUG)) {
                Log.d(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
                        + "expected state " + newState + " found " + f.mState);
            }
            f.mState = newState;
        }
    }

4.8 终于到fragment的生命周期执行

  • 这里有一个FragmentStateManager,就是他才是真正的调用Fragment 的生命周期方法,我们终于看到熟悉的身影,Fragment 的 onCreateView方法。
  • 这里看onCreateView ,我们最常用的方法,其他也是一样样的,大家也可以尝试自己去分析。
 case Fragment.CREATED:                    
       if (newState > Fragment.CREATED) {
           fragmentStateManager.createView();
       }


    /*FragmentStateManager*/
     void createView() {
        ...
        mFragment.performCreateView(layoutInflater, container, mFragment.mSavedFragmentState);
        ...
     }

    /*Fragment*/
     void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        mChildFragmentManager.noteStateNotSaved();
        mPerformedCreateView = true;
        mViewLifecycleOwner = new FragmentViewLifecycleOwner(getViewModelStore());
        mView = onCreateView(inflater, container, savedInstanceState);
        if (mView != null) {
            // Initialize the view lifecycle
            mViewLifecycleOwner.initialize();
            // Tell the fragment's new view about it before we tell anyone listening
            // to mViewLifecycleOwnerLiveData and before onViewCreated, so that calls to
            // ViewTree get() methods return something meaningful
            ViewTreeLifecycleOwner.set(mView, mViewLifecycleOwner);
            ViewTreeViewModelStoreOwner.set(mView, mViewLifecycleOwner);
            ViewTreeSavedStateRegistryOwner.set(mView, mViewLifecycleOwner);
            // Then inform any Observers of the new LifecycleOwner
            mViewLifecycleOwnerLiveData.setValue(mViewLifecycleOwner);
        } else {
            if (mViewLifecycleOwner.isInitialized()) {
                throw new IllegalStateException("Called getViewLifecycleOwner() but "
                        + "onCreateView() returned null");
            }
            mViewLifecycleOwner = null;
        }
    }

5.流程图

  • 搭配流程图看可能会好一些。


    流程图
  • 如果有错帮忙指出,谢谢。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容