Fragment生命周期源码分析

Posted 白嫩豆腐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fragment生命周期源码分析相关的知识,希望对你有一定的参考价值。

前言

上一篇介绍了Fragment的新建过程,这一篇我们介绍一下Fragment的生命周期源码的过程,这里我们假设的情景是fragment已经添加到页面上了,通过上一篇我们知道Fragment其实就是activity的一个成员变量,用来提供一个view,所以Fragment的生命周期肯定是activity控制的(其实activitymanageservice也可以控制,但是完全没必要那么复杂),所以我们就直接看activity源码即可,可是我们忽然发现androidx.fragment.app.Fragment其实是一个第三方库,那么我们的系统一般没必要引用第三方库,我们会发现系统其实有一个叫android.app.Fragment。所以说控制Fragment生命周期的肯定是第三方库。我们只要跟进第三方库即可

正文

前言说了一大堆东东,其实就可以得到一个结论

我们用的androidx.fragment.app.Fragment声明周期的控制是FragmentActivity
那我们直接看FragmentActivity源码,简短版大概是这样:


public class FragmentActivity extends ComponentActivity
   
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        //恢复数据
        if (savedInstanceState != null) 
           ......
        
        mFragments.dispatchCreate();
    

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) 
        final View v = dispatchFragmentsOnCreateView(parent, name, context, attrs);
    

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) 
        final View v = dispatchFragmentsOnCreateView(null, name, context, attrs);
    

    final View dispatchFragmentsOnCreateView(View parent, String name, Context context,
            AttributeSet attrs) 
        return mFragments.onCreateView(parent, name, context, attrs);
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        mFragments.dispatchDestroy();
    

  
    @Override
    protected void onPause() 
        super.onPause();
        mResumed = false;
        if (mHandler.hasMessages(MSG_RESUME_PENDING)) 
            mHandler.removeMessages(MSG_RESUME_PENDING);
            onResumeFragments();
        
        mFragments.dispatchPause();
    

    @Override
    protected void onResume() 
        super.onResume();
        mHandler.sendEmptyMessage(MSG_RESUME_PENDING);
        mResumed = true;
        mFragments.execPendingActions();
    

    @Override
    protected void onPostResume() 
        super.onPostResume();
        mHandler.removeMessages(MSG_RESUME_PENDING);
        onResumeFragments();
        mFragments.execPendingActions();
    
    protected void onResumeFragments() 
        mFragments.dispatchResume();
    

    @Override
    protected void onStart() 
        super.onStart();

        mStopped = false;

        if (!mCreated) 
            mCreated = true;
            mFragments.dispatchActivityCreated();
        

        mFragments.noteStateNotSaved();
        mFragments.execPendingActions();
        mFragments.dispatchStart();
    

    @Override
    protected void onStop() 

        markFragmentsCreated();

        mFragments.dispatchStop();
    

emmm 看完以后忽然觉得这个代码好整齐呀,如果结合上一篇博客,会有种豁然开朗的感觉,他不就是把自己的状态告诉Fragment,然后就完事了,不过我们稍微留意一下,有些生命周期为了代码健壮性,搞了一些奇怪的代码,但是我们很简单的理解,就按照activity的生命周期来分析一下Fragment到底是如何工作的。
我们从oncreat()开始

    public void dispatchCreate() 
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.CREATED);
    
   private void dispatchStateChange(int nextState) 
        try 
            mExecutingActions = true;
            moveToState(nextState, false);
         finally 
            mExecutingActions = false;
        
        execPendingActions();
    

熟悉之前代码的,就会对现在这个代码很熟悉了,execPendingActions这个函数其实就是加入Fragment或者用来暂时加入栈操作的,这个因为对我们的Fragment状态是毫无影响的,所以很容易推断,他就是在 moveToState(nextState, false)中操作的,我们进去看看吧:

void moveToState(int newState, boolean always) 
	
	mCurState = newState;
	if (mActive != null) 

		// Must add them in the proper order. mActive fragments may be out of order
		final int numAdded = mAdded.size();
		for (int i = 0; i < numAdded; i++) 
			Fragment f = mAdded.get(i);
			moveFragmentToExpectedState(f);
		

		// Now iterate through all active fragments. These will include those that are removed
		// and detached.
		final int numActive = mActive.size();
		for (int i = 0; i < numActive; i++) 
			Fragment f = mActive.valueAt(i);
			if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) 
				moveFragmentToExpectedState(f);
			
		

		//这个是处理一些延迟处理的东东,可以忽视
		startPendingDeferredFragments();
		......
	

看下注释,第一个是循环中,就让Fragment处于正常状态,我们刚才已经改变了Fragment的状态,很容易理解就是这里来处理的,
第二个是处理remove和detach的,我们只要跟踪moveFragmentToExpectedState就ok了。

void moveFragmentToExpectedState(Fragment f) 
	......
	moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);

	//Fragment添加是有顺序的,这里每次改变后,都把Fragment给调到最高层,主要是为了适应刚才的那个循环,肯定是后加入的,最后会显示在屏幕上
	//还有的是为了动画,


oid moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) 
switch (f.mState) 
	case Fragment.CREATED:
	// This is outside the if statement below on purpose; we want this to run
	// even if we do a moveToState from CREATED => *, CREATED => CREATED, and
	// * => CREATED as part of the case fallthrough above.
	ensureInflatedFragmentView(f);

	if (newState > Fragment.CREATED) 
	
		if (!f.mFromLayout) 
			ViewGroup container = null;
			if (f.mContainerId != 0) 
			......
				container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
				......
			
			f.mContainer = container;
			//调用oncreatView
			f.performCreateView(f.performGetLayoutInflater(
					f.mSavedFragmentState), container, f.mSavedFragmentState);
				f.mInnerView = f.mView;
					container.addView(f.mView);
				f.onViewCreated(f.mView, f.mSavedFragmentState);
				dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
						false);
				// Only animate the view if it is visible. This is done after
				// dispatchOnFragmentViewCreated in case visibility is changed
				f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
						&& f.mContainer != null;
			 else 
				f.mInnerView = null;
			
		

		f.performActivityCreated(f.mSavedFragmentState);
		dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
		if (f.mView != null) 
			f.restoreViewState(f.mSavedFragmentState);
		
		f.mSavedFragmentState = null;
	
	// fall through
	case Fragment.ACTIVITY_CREATED:
	if (newState > Fragment.ACTIVITY_CREATED) 
		if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
		f.performStart();
		dispatchOnFragmentStarted(f, false);
	
	// fall through
	case Fragment.STARTED:
	if (newState > Fragment.STARTED) 
		if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
		f.performResume();
		dispatchOnFragmentResumed(f, false);
		f.mSavedFragmentState = null;
		f.mSavedViewState = null;
	

函数大概就这样,很容易看到当activity声明周期到了oncreat时候,Fragment走过了三个生命周期。但是我们在第一个周期中

最后发现这里的给分析都是错的,因为mHost.getHandler().post(mExecCommit);一直要到activity的onresume中才会执行,我们代码分析完全都是错的。其实所有的声明周期相关的都是在


    @Override
    protected void onStart() 
        super.onStart();

        mStopped = false;

        if (!mCreated) 
            mCreated = true;
            mFragments.dispatchActivityCreated();
        

        mFragments.noteStateNotSaved();
        mFragments.execPendingActions();
        mFragments.dispatchStart();
    

中执行的,代码和上面流程一样,只是吧改变声明周期的代码放入到直接的函数调用中了。有机会在重新分析一下Android的 消息分发流程。这里就暂时不在详细追究了。

后记

因为中间好多交叉知识点。我还以为是activity的声明周期影响的呢,最后发现仅仅是Android消息机制的影响,以后可以再分析一下Android的消息通讯机制。这里就暂时到这里,其实这个东西也没什么好过多详细介绍的

以上是关于Fragment生命周期源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Fragment 生命周期源码分析

Fragment 生命周期源码分析

Glide 4.12 框架源码中的生命周期设计

Glide 4.12 框架源码中的生命周期设计

Glide 4.12 框架源码中的生命周期设计

Glide 4.12 框架源码中的生命周期设计