Fragment、DialogFragment和BottomSheetDialogFragment生命周期流程源码解析

一、Fragment1.1 生命周期官方网上的Fragment声明周期。​图 1 Fragment生命周期流程图除了上述声明周期之外,也可以注册FragmentLifecycleCallbacks来插入更多Fragment状态的监听,具体有:public abstract static class FragmentLifecycleCallbacks { /** * Called right before the fragment's {@link Fragme
摘要由CSDN通过智能技术生成

一、Fragment

1.1 生命周期

官方网上的Fragment声明周期。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XvcxqLFt-1634898790473)(/Users/mtdp/Library/Application Support/typora-user-images/image-20211022174424557.png)]
​图 1 Fragment生命周期流程图

除了上述声明周期之外,也可以注册FragmentLifecycleCallbacks来插入更多Fragment状态的监听,具体有:

public abstract static class FragmentLifecycleCallbacks {
   
        /**
         * Called right before the fragment's {@link Fragment#onAttach(Context)} method is called.
         * This is a good time to inject any required dependencies or perform other configuration
         * for the fragment before any of the fragment's lifecycle methods are invoked.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param context Context that the Fragment is being attached to
         */
        public void onFragmentPreAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
                @NonNull Context context) {
   }

        /**
         * Called after the fragment has been attached to its host. Its host will have had
         * <code>onAttachFragment</code> called before this call happens.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param context Context that the Fragment was attached to
         */
        public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
                @NonNull Context context) {
   }

        /**
         * Called right before the fragment's {@link Fragment#onCreate(Bundle)} method is called.
         * This is a good time to inject any required dependencies or perform other configuration
         * for the fragment.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param savedInstanceState Saved instance bundle from a previous instance
         */
        public void onFragmentPreCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
                @Nullable Bundle savedInstanceState) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onCreate(Bundle)}. This will only happen once for any given
         * fragment instance, though the fragment may be attached and detached multiple times.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param savedInstanceState Saved instance bundle from a previous instance
         */
        public void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
                @Nullable Bundle savedInstanceState) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onActivityCreated(Bundle)}. This will only happen once for any given
         * fragment instance, though the fragment may be attached and detached multiple times.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param savedInstanceState Saved instance bundle from a previous instance
         */
        public void onFragmentActivityCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
                @Nullable Bundle savedInstanceState) {
   }

        /**
         * Called after the fragment has returned a non-null view from the FragmentManager's
         * request to {@link Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment that created and owns the view
         * @param v View returned by the fragment
         * @param savedInstanceState Saved instance bundle from a previous instance
         */
        public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
                @NonNull View v, @Nullable Bundle savedInstanceState) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onStart()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentStarted(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onResume()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onPause()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentPaused(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onStop()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentStopped(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onSaveInstanceState(Bundle)}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         * @param outState Saved state bundle for the fragment
         */
        public void onFragmentSaveInstanceState(@NonNull FragmentManager fm, @NonNull Fragment f,
                @NonNull Bundle outState) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onDestroyView()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentViewDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onDestroy()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }

        /**
         * Called after the fragment has returned from the FragmentManager's call to
         * {@link Fragment#onDetach()}.
         *
         * @param fm Host FragmentManager
         * @param f Fragment changing state
         */
        public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
   }
    }

所以,如果考虑开发中自己注册的状态变化监听,那么其方法调用过程如下图

在这里插入图片描述
图 2 Fragment生命周期及FragmentLifecycleCallbacks流程图

1.2 生命周期执行顺序源码解析

1、Fragment的提交并展示

通常我们使用下列代码来提交并展示一个Fragment

XXXFragment fragment = new XXXFragment();
Bundle bundle = new Bundle();
bundle.putString("key", "value");
fragment.setAurguments(bundle);
// 或者commitAllowStateLoss
getSupportFragmentManager.beginTransaction().add(R.id.xxx, fragment).commit(); 

添加Fragment视图的方式有很多,例如add()、replace()

这里已add()方法为例,看下代码实现。(重要代码位置处通过注释标明了序号①②③…

// FragmentTransaction.java
......
/**
* Calls {@link #add(int, Fragment, String)} with a 0 containerViewId.
*/
@NonNull
public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag)  {
   
	doAddOp(0, fragment, tag, OP_ADD);
	return this;
}
...... 
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
   
        final Class<?> fragmentClass = fragment.getClass();
        final int modifiers = fragmentClass.getModifiers();
        if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
                || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
   
            throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
                    + " must be a public static class to be  properly recreated from"
                    + " instance state.");
        }
        if (tag != null) {
   
            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
   
                throw new IllegalStateException("Can't change tag of fragment "
                        + fragment + ": was " + fragment.mTag
                        + " now " + tag);
            }
            fragment.mTag = tag;
        }
        if (containerViewId != 0) {
   
            if (containerViewId == View.NO_ID) {
   
                throw new IllegalArgumentException("Can't add fragment "
                        + fragment + " with tag " + tag + " to container view with no id");
            }
            if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
   
                throw new IllegalStateException("Can't change container ID of fragment "
                        + fragment + ": was " + fragment.mFragmentId
                        + " now " + containerViewId);
            }
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        addOp(new Op(opcmd, fragment));
    }
......
void addOp(Op op) {
   
        mOps.add(op);
        op.mEnterAnim = mEnterAnim;
        op.mExitAnim = mExitAnim;
        op.mPopEnterAnim = mPopEnterAnim;
        op.mPopExitAnim = mPopExitAnim;
    }

代码看似很多,其实主要目的是将OP_ADD这一指令保存在列表中,然后接着看commit()

// BackStackRecord.java

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

int commitInternal(boolean allowStateLoss) {
   
	if (mCommitted) throw new IllegalStateException("commit already called");
	if (FragmentManagerImpl.DEBUG) {
   
		Log.v(TAG, "Commit: " + this);
		LogWriter logw = new LogWriter(TAG);
		PrintWriter pw = new PrintWriter(logw);
		dump("  ", pw);
		pw.close();	
  }
	mCommitted = true;
	if (mAddToBackStack) {
   
		mIndex = mManager.allocBackStackIndex(this);
	} else {
   
		mIndex = -1;
	}
  	
  	//** ① **/ 
	mManager.enqueueAction(this, allowStateLoss);
	return mIndex;
}

①:将提交Fragment事件添加到执行队列中等待执行。

继续深入查看代码,mManagerFragmentManagerImpl对象,执行它的enqueueAction()方法。

 		// FragmentManagerImpl.java

		/**
     * Adds an action to the queue of pending actions.
     *
     * @param action the action to add
     * @param allowStateLoss whether to allow loss of state information
     * @throws IllegalStateException if the activity has been destroyed
     */
    public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
   
        if (!allowStateLoss) {
   
            checkStateLoss();
        }
        synchronized (this) {
   
            if (mDestroyed || mHost == null) {
   
                if (allowStateLoss) {
   
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
   
                mPendingActions = new ArrayList<>();
            }
            // ** ② **/
            mPendingActions.add(action);
            scheduleCommit();
        }
    }

		/**
     * Schedules the execution when one hasn't been scheduled already. This should happen
     * the first time {@link #enqueueAction(OpGenerator, boolean)} is called or when
     * a postponed transaction has been started with
     * {@link Fragment#startPostponedEnterTransition()}
     */
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void scheduleCommit() {
   
        synchronized (this) {
   
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
          	// ** ③ **/
            boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
   
                mHost.getHandler().removeCallbacks(mExecCommit);
              	// ** ④ **/
                mHost.getHandler().post(mExecCommit);
                updateOnBackPressedCallbackEnabled();
            }
        }
    }

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

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

        boolean didSomethin
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值