美文网首页
Fragment(一)

Fragment(一)

作者: 涛涛123759 | 来源:发表于2021-11-09 15:20 被阅读0次

    Android知识总结

    一、Fragment 的使用

    实现很简单,创建一个的布局,然后在 Activity 里点击时替换 Fragment。

    mFragmentManager = getSupportFragmentManager();
    mFragmentManager.beginTransaction()
     .replace(R.id.fl_content, fragment)
     .commitAllowingStateLoss();
    

    代码很简单,核心就三步:

      1. 创建 Fragment
      1. 获取 FragmentManager
      1. 调用事务,添加、替换
    执行流程图

    二、FragmentManager

    FragmentManager 是一个抽象类,定义了一些和 Fragment 相关的操作和内部类/接口。

    public abstract class FragmentManager { ... }
    

    2.1、FragmentManager 中定义的方法如下:

    //开启一系列对 Fragments 的操作
    public abstract FragmentTransaction beginTransaction();
    //FragmentTransaction.commit() 是异步执行的,如果你想立即执行,可以调用这个方法
    public abstract boolean executePendingTransactions();
    //根据 ID 找到从 XML 解析出来的或者事务中添加的 Fragment
    //首先会找添加到 FragmentManager 中的,找不到就去回退栈里找
    public abstract Fragment findFragmentById(@IdRes int id);
    //跟上面的类似,不同的是使用 tag 进行查找
    public abstract Fragment findFragmentByTag(String tag);
    //弹出回退栈中栈顶的 Fragment,异步执行的
    public abstract void popBackStack();
    //立即弹出回退栈中栈顶的,直接执行哦
    public abstract boolean popBackStackImmediate();
    
    //返回栈顶符合名称的,如果传入的 name 不为空,在栈中间找到了 Fragment,那将弹出这个Fragment 上面的所有 Fragment
    //有点类似启动模式的 singleTask 的感觉
    //如果传入的 name 为 null,那就和 popBackStack() 一样了
    //异步执行
    public abstract void popBackStack(String name, int flags);
    //同步版的上面
    public abstract boolean popBackStackImmediate(String name, int flags);
    //和使用 name 查找、弹出一样
    //不同的是这里的 id 是 FragmentTransaction.commit() 返回的 id
    public abstract void popBackStack(int id, int flags);
    //你懂得
    public abstract boolean popBackStackImmediate(int id, int flags);
    //获取回退栈中的元素个数
    public abstract int getBackStackEntryCount();
    //根据索引获取回退栈中的某个元素
    public abstract BackStackEntry getBackStackEntryAt(int index);
    //添加或者移除一个监听器
    public abstract void
    addOnBackStackChangedListener(OnBackStackChangedListener listener);
    public abstract void
    removeOnBackStackChangedListener(OnBackStackChangedListener listener);
    //还定义了将一个 Fragment 实例作为参数传递
    public abstract void putFragment(Bundle bundle, String key, Fragment
    fragment);
    public abstract Fragment getFragment(Bundle bundle, String key);
    //获取 manager 中所有添加进来的 Fragment
    public abstract List<Fragment> getFragments();
    

    可以看到,定义的方法有很多是异步执行的。

    2.2、内部类/接口

    • BackStackEntry:Fragment 后退栈中的一个元素
    • onBackStackChangedListener:后退栈变动监听器
    • FragmentLifecycleCallbacks: FragmentManager 中的 Fragment 生命周期监听
    //后退栈中的一个元素
    public interface BackStackEntry {
      //栈中该元素的唯一标识
      public int getId();
      //获取 FragmentTransaction#addToBackStack(String) 设置的名称
      public String getName();
      @StringRes
      public int getBreadCrumbTitleRes();
      @StringRes
      public int getBreadCrumbShortTitleRes();
      public CharSequence getBreadCrumbTitle();
      public CharSequence getBreadCrumbShortTitle();
    }
    

    可以看到 BackStackEntry 的接口比较简单,关键信息就是 ID 和 Name

    //在 Fragment 回退栈中有变化时回调
    public interface OnBackStackChangedListener {
      public void onBackStackChanged();
    }
    
    //FragmentManager 中的 Fragment 生命周期监听
    public abstract static class FragmentLifecycleCallbacks {
        public void onFragmentPreAttached(FragmentManager fm, Fragment f,Context context) {}
        public void onFragmentAttached(FragmentManager fm, Fragment f,Context context) {}
        public void onFragmentCreated(FragmentManager fm, Fragment f,Bundle savedInstanceState) {}
        public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {}
        public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {}
        public void onFragmentStarted(FragmentManager fm, Fragment f) {}
        public void onFragmentResumed(FragmentManager fm, Fragment f) {}
        public void onFragmentPaused(FragmentManager fm, Fragment f) {}
        public void onFragmentStopped(FragmentManager fm, Fragment f) {}
        public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {}
        public void onFragmentViewDestroyed(FragmentManager fm, Fragment f){}
        public void onFragmentDestroyed(FragmentManager fm, Fragment f) {}
        public void onFragmentDetached(FragmentManager fm, Fragment f) {}
     }
    }
    

    熟悉 Fragment 生命周期的同学一定觉得很面熟,这个接口就是为我们提供一个 FragmentManager 所有 Fragment 生命周期变化的回调。

    可以看到, FragmentManager 是一个抽象类,它定义了对一个 Activity/Fragment 中 添加进来的Fragment 列表、Fragment 回退栈的操作、管理

    三、FragmentManagerImpl

    FragmentManager 定义的任务是由 FragmentManagerImpl 实现的。

    final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    
        static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
        static final String TARGET_STATE_TAG = "android:target_state";
        static final String VIEW_STATE_TAG = "android:view_state";
        static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
    
        private static final class FragmentLifecycleCallbacksHolder {
            final FragmentLifecycleCallbacks mCallback;
            final boolean mRecursive;
    
            FragmentLifecycleCallbacksHolder(FragmentLifecycleCallbacks callback, boolean recursive) {
                mCallback = callback;
                mRecursive = recursive;
            }
        }
    
        ArrayList<OpGenerator> mPendingActions;
        boolean mExecutingActions;
    
        int mNextFragmentIndex = 0;
        //保存活跃 fragment 集合
        final ArrayList<Fragment> mAdded = new ArrayList<>();
         //保存添加 fragment 集合
        final HashMap<String, Fragment> mActive = new HashMap<>();
        //回退栈集合
        ArrayList<BackStackRecord> mBackStack;
        ArrayList<Fragment> mCreatedMenus;
        private OnBackPressedDispatcher mOnBackPressedDispatcher;
        private final OnBackPressedCallback mOnBackPressedCallback =
                new OnBackPressedCallback(false) {
            @Override
            public void handleOnBackPressed() {
                FragmentManagerImpl.this.handleOnBackPressed();
            }
        };
    
        // Must be accessed while locked.
        ArrayList<BackStackRecord> mBackStackIndices;
        ArrayList<Integer> mAvailBackStackIndices;
    
        ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
        private final CopyOnWriteArrayList<FragmentLifecycleCallbacksHolder>
                mLifecycleCallbacks = new CopyOnWriteArrayList<>();
    
        int mCurState = Fragment.INITIALIZING;
        FragmentHostCallback mHost;
        FragmentContainer mContainer;
        Fragment mParent;
        @Nullable
        Fragment mPrimaryNav;
    
        boolean mNeedMenuInvalidate;
        boolean mStateSaved;
        boolean mStopped;
        boolean mDestroyed;
        boolean mHavePendingDeferredStart;
    
        // Temporary vars for removing redundant operations in BackStackRecords:
        ArrayList<BackStackRecord> mTmpRecords;
        ArrayList<Boolean> mTmpIsPop;
        ArrayList<Fragment> mTmpAddedFragments;
    
        // 用于状态保存和恢复的临时变量
        Bundle mStateBundle = null;
        SparseArray<Parcelable> mStateArray = null;
    
        // Postponed transactions.
        ArrayList<StartEnterTransitionListener> mPostponedTransactions;
    
        private FragmentManagerViewModel mNonConfig;
    }
    

    四、事务

    BackStackRecord (事务真正实现/回退栈)继承了 FragmentTransaction :

    final class BackStackRecord extends FragmentTransaction implements
            FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
        static final String TAG = FragmentManagerImpl.TAG;
        //维护 FragmentManager
        final FragmentManagerImpl mManager;
    
        boolean mCommitted;
        int mIndex = -1;
        ...
    }
    

    4.1、FragmentTransaction

    FragmentTransaction 定义了一系列对 Fragment 的操作方法:

    //它会调用 add(int, Fragment, String),其中第一个参数传的是 0
    public abstract FragmentTransaction add(Fragment fragment, String tag)
    
    //它会调用 add(int, Fragment, String),其中第三个参数是 null
    public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);
    
    //添加一个 Fragment 给 Activity 的最终实现
    //第一个参数表示 Fragment 要放置的布局 id
    //第二个参数表示要添加的 Fragment,【注意】一个 Fragment 只能添加一次
    //第三个参数选填,可以给 Fragment 设置一个 tag,后续可以使用这个 tag 查询它
    public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment, @Nullable String tag);
    
    //调用 replace(int, Fragment, String),第三个参数传的是 null
    public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment);
    
    //替换宿主中一个已经存在的 fragment
    //这一个方法等价于先调用 remove(), 再调用 add()
    public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment, @Nullable String tag);
    
    //移除一个已经存在的 fragment
    //如果之前添加到宿主上,那它的布局也会被移除
    public abstract FragmentTransaction remove(Fragment fragment);
    
    //隐藏一个已存的 fragment
    //其实就是将添加到宿主上的布局隐藏
    public abstract FragmentTransaction hide(Fragment fragment);
    
    //显示前面隐藏的 fragment,这只适用于之前添加到宿主上的 fragment
    public abstract FragmentTransaction show(Fragment fragment);
    
    //将指定的 fragment 将布局上解除
    //当调用这个方法时,fragment 的布局已经销毁了
    public abstract FragmentTransaction detach(Fragment fragment);
    
    //当前面解除一个 fragment 的布局绑定后,调用这个方法可以重新绑定
    //这将导致该 fragment 的布局重建,然后添加、展示到界面上
    public abstract FragmentTransaction attach(Fragment fragment);
    

    4.2、事务的四种提交方式

    事务最终的提交方法有四种:

      1. commit()
      1. commitAllowingStateLoss()
      1. commitNow()
      1. commitNowAllowingStateLoss(

    它们之间的特点及区别如下:

    public abstract int commit();
    

    commit() 在主线程中异步执行,其实也是 Handler 抛出任务,等待主线程调度执行。

    注意:
    commit() 需要在宿主 Activity 保存状态之前调用,否则会报错。
    这是因为如果 Activity 出现异常需要恢复状态,在保存状态之后的 commit() 将会丢失,这和调用的初衷不符,所以会报错。

    public abstract int commitAllowingStateLoss();
    

    commitAllowingStateLoss() 也是异步执行,但它的不同之处在于,允许在 Activity 保存状态之后调用,也就是说它遇到状态丢失不会报错。
    因此我们一般在界面状态出错是可以接受的情况下使用它。

    public abstract void commitNow();
    

    commitNow() 是同步执行的,立即提交任务。
    前面提到 FragmentManager.executePendingTransactions() 也可以实现立即提交事务。但我们一般建议使用 commitNow() , 因为另外那位是一下子执行所有待执行的任务,可能会把当前所有的事务都一下子执行了,这有可能有副作用。

    此外,这个方法提交的事务可能不会被添加到 FragmentManger 的后退栈,因为你这样直接提交,有可能影响其他异步执行任务在栈中的顺序。

    和 commit() 一样, commitNow() 也必须在 Activity 保存状态前调用,否则会抛异常。

    public abstract void commitNowAllowingStateLoss();
    

    同步执行的 commitNowAllowingStateLoss() >

    五、保存状态

    FragmentActivity执行onSaveInstanceState

        static final String FRAGMENTS_TAG = "android:support:fragments";
        static final String NEXT_CANDIDATE_REQUEST_INDEX_TAG = "android:support:next_request_index";
        static final String ALLOCATED_REQUEST_INDICIES_TAG = "android:support:request_indicies";
        static final String REQUEST_FRAGMENT_WHO_TAG = "android:support:request_fragment_who";
    
        protected void onSaveInstanceState(@NonNull Bundle outState) {
            super.onSaveInstanceState(outState);
            markFragmentsCreated();
            mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
            Parcelable p = mFragments.saveAllState();
            if (p != null) {
                outState.putParcelable(FRAGMENTS_TAG, p);
            }
            if (mPendingFragmentActivityResults.size() > 0) {
                outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);
    
                int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
                String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
                for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
                    requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
                    fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
                }
                outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
                outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
            }
        }
    

    执行FragmentController#saveAllState

        private final FragmentHostCallback<?> mHost;
    
        public Parcelable saveAllState() {
            return mHost.mFragmentManager.saveAllState();
        }
    

    执行FragmentManagerImpl#saveAllState保存状态

        Parcelable saveAllState() {
            // Make sure all pending operations have now been executed to get
            // our state update-to-date.
            forcePostponedTransactions();
            endAnimatingAwayFragments();
            execPendingActions();
            //保存标记,标志位至 true
            mStateSaved = true;
    
            if (mActive.isEmpty()) {
                return null;
            }
    
            // First collect all active fragments.
            int size = mActive.size();
            ArrayList<FragmentState> active = new ArrayList<>(size);
            boolean haveFragments = false;
            for (Fragment f : mActive.values()) {
                if (f != null) {
                    if (f.mFragmentManager != this) {
                        throwException(new IllegalStateException(
                                "Failure saving state: active " + f
                                        + " was removed from the FragmentManager"));
                    }
    
                    haveFragments = true;
                    //用于保存fragment的成员变量
                    FragmentState fs = new FragmentState(f);
                    active.add(fs);
    
                    if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
                        //这里面会保存view树
                        fs.mSavedFragmentState = saveFragmentBasicState(f);
    
                        if (f.mTargetWho != null) {
                            Fragment target = mActive.get(f.mTargetWho);
                            if (target == null) {
                                throwException(new IllegalStateException(
                                        "Failure saving state: " + f
                                                + " has target not in fragment manager: "
                                                + f.mTargetWho));
                            }
                            if (fs.mSavedFragmentState == null) {
                                fs.mSavedFragmentState = new Bundle();
                            }
                            putFragment(fs.mSavedFragmentState,
                                    FragmentManagerImpl.TARGET_STATE_TAG, target);
                            if (f.mTargetRequestCode != 0) {
                                fs.mSavedFragmentState.putInt(
                                        FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
                                        f.mTargetRequestCode);
                            }
                        }
    
                    } else {
                        fs.mSavedFragmentState = f.mSavedFragmentState;
                    }
    
                    if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
                            + fs.mSavedFragmentState);
                }
            }
    
            if (!haveFragments) {
                if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
                return null;
            }
    
            ArrayList<String> added = null;
            BackStackState[] backStack = null;
    
            // Build list of currently added fragments.
            size = mAdded.size();
            if (size > 0) {
                added = new ArrayList<>(size);
                for (Fragment f : mAdded) {
                    //这里开始保存fragment的唯一标识
                    added.add(f.mWho);
                    if (f.mFragmentManager != this) {
                        throwException(new IllegalStateException(
                                "Failure saving state: active " + f
                                        + " was removed from the FragmentManager"));
                    }
                    if (DEBUG) {
                        Log.v(TAG, "saveAllState: adding fragment (" + f.mWho
                                + "): " + f);
                    }
                }
            }
    
            //保存回退栈信息
            if (mBackStack != null) {
                size = mBackStack.size();
                if (size > 0) {
                    backStack = new BackStackState[size];
                    for (int i = 0; i < size; i++) {
                        backStack[i] = new BackStackState(mBackStack.get(i));
                        if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
                                + ": " + mBackStack.get(i));
                    }
                }
            }
            //保存FragmentManagerImpl的整体信息
            FragmentManagerState fms = new FragmentManagerState();
            fms.mActive = active;
            fms.mAdded = added;
            fms.mBackStack = backStack;
            if (mPrimaryNav != null) {
                fms.mPrimaryNavActiveWho = mPrimaryNav.mWho;
            }
            fms.mNextFragmentIndex = mNextFragmentIndex;
            return fms;
        }
    

    六、恢复状态

    FragmentActivity#onCreate中方进行恢复

        protected void onCreate(@Nullable Bundle savedInstanceState) {
            mFragments.attachHost(null /*parent*/);
    
            if (savedInstanceState != null) {
                Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
                //把之前保存的数据取回来
                mFragments.restoreSaveState(p);
    
                // Check if there are any pending onActivityResult calls to descendent Fragments.
                if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
                    mNextCandidateRequestIndex =
                            savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
                    int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
                    String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
                    if (requestCodes == null || fragmentWhos == null ||
                            requestCodes.length != fragmentWhos.length) {
                        Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
                    } else {
                        mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
                        for (int i = 0; i < requestCodes.length; i++) {
                            mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                        }
                    }
                }
            }
    
            if (mPendingFragmentActivityResults == null) {
                mPendingFragmentActivityResults = new SparseArrayCompat<>();
                mNextCandidateRequestIndex = 0;
            }
    
            super.onCreate(savedInstanceState);
            //更改状态
            mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
            //分发 炽热create 事件
            mFragments.dispatchCreate();
        }
    

    执行FragmentController#restoreSaveState

        public void restoreSaveState(@Nullable Parcelable state) {
            if (!(mHost instanceof ViewModelStoreOwner)) {
                throw new IllegalStateException("Your FragmentHostCallback must implement "
                        + "ViewModelStoreOwner to call restoreSaveState(). Call restoreAllState() "
                        + " if you're still using retainNestedNonConfig().");
            }
            mHost.mFragmentManager.restoreSaveState(state);
        }
    

    执行FragmentManagerImpl#restoreSaveState恢复数据

        void restoreSaveState(Parcelable state) {
            // If there is no saved state at all, then there's nothing else to do
            if (state == null) return;
            FragmentManagerState fms = (FragmentManagerState)state;
            if (fms.mActive == null) return;
    
            // First re-attach any non-config instances we are retaining back
            // to their saved state, so we don't try to instantiate them again.
            for (Fragment f : mNonConfig.getRetainedFragments()) {
                if (DEBUG) Log.v(TAG, "restoreSaveState: re-attaching retained " + f);
                FragmentState fs = null;
                for (FragmentState fragmentState : fms.mActive) {
                    if (fragmentState.mWho.equals(f.mWho)) {
                        fs = fragmentState;
                        break;
                    }
                }
                if (fs == null) {
                    if (DEBUG) {
                        Log.v(TAG, "Discarding retained Fragment " + f
                                + " that was not found in the set of active Fragments " + fms.mActive);
                    }
                    // 重新执行fragment生命周期.
                    moveToState(f, Fragment.CREATED, 0, 0, false);
                    f.mRemoving = true;
                    moveToState(f, Fragment.INITIALIZING, 0, 0, false);
                    continue;
                }
                fs.mInstance = f;
                f.mSavedViewState = null;
                f.mBackStackNesting = 0;
                f.mInLayout = false;
                f.mAdded = false;
                f.mTargetWho = f.mTarget != null ? f.mTarget.mWho : null;
                f.mTarget = null;
                if (fs.mSavedFragmentState != null) {
                    fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                    f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                            FragmentManagerImpl.VIEW_STATE_TAG);
                    f.mSavedFragmentState = fs.mSavedFragmentState;
                }
            }
    
            // Build the full list of active fragments, instantiating them from
            // their saved state.
            mActive.clear();
            for (FragmentState fs : fms.mActive) {
                if (fs != null) {
                    Fragment f = fs.instantiate(mHost.getContext().getClassLoader(),
                            getFragmentFactory());
                    f.mFragmentManager = this;
                    if (DEBUG) Log.v(TAG, "restoreSaveState: active (" + f.mWho + "): " + f);
                    mActive.put(f.mWho, f);
                    // Now that the fragment is instantiated (or came from being
                    // retained above), clear mInstance in case we end up re-restoring
                    // from this FragmentState again.
                    fs.mInstance = null;
                }
            }
    
            // Build the list of currently added fragments.
            mAdded.clear();
            if (fms.mAdded != null) {
                for (String who : fms.mAdded) {
                    Fragment f = mActive.get(who);
                    if (f == null) {
                        throwException(new IllegalStateException(
                                "No instantiated fragment for (" + who + ")"));
                    }
                    f.mAdded = true;
                    if (DEBUG) Log.v(TAG, "restoreSaveState: added (" + who + "): " + f);
                    if (mAdded.contains(f)) {
                        throw new IllegalStateException("Already added " + f);
                    }
                    synchronized (mAdded) {
                        mAdded.add(f);
                    }
                }
            }
    
            // Build the back stack.
            if (fms.mBackStack != null) {
                mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
                for (int i=0; i<fms.mBackStack.length; i++) {
                    BackStackRecord bse = fms.mBackStack[i].instantiate(this);
                    if (DEBUG) {
                        Log.v(TAG, "restoreAllState: back stack #" + i
                                + " (index " + bse.mIndex + "): " + bse);
                        LogWriter logw = new LogWriter(TAG);
                        PrintWriter pw = new PrintWriter(logw);
                        bse.dump("  ", pw, false);
                        pw.close();
                    }
                    mBackStack.add(bse);
                    if (bse.mIndex >= 0) {
                        setBackStackIndex(bse.mIndex, bse);
                    }
                }
            } else {
                mBackStack = null;
            }
    
            if (fms.mPrimaryNavActiveWho != null) {
                mPrimaryNav = mActive.get(fms.mPrimaryNavActiveWho);
                dispatchParentPrimaryNavigationFragmentChanged(mPrimaryNav);
            }
            this.mNextFragmentIndex = fms.mNextFragmentIndex;
        }
    

    七、添加一个 Fragment 到布局 add() 的实现

    执行FragmentTransaction#add

        @NonNull
        public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag)  {
            doAddOp(0, fragment, tag, OP_ADD);
            return this;
        }
        @NonNull
        public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
            doAddOp(containerViewId, fragment, null, OP_ADD);
            return this;
        }
    
        @NonNull
        public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment,
                @Nullable String tag) {
            doAddOp(containerViewId, fragment, tag, OP_ADD);
            return this;
        }
    

    执行FragmentTransaction#doAddOp

        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);
                }
                //设置 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);
                }
                //设置宿主 ID 为布局 ID
                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;
        }
    

    接下来看new Op(opcmd, fragment)

        static final class Op {
            int mCmd;
            Fragment mFragment;
            int mEnterAnim;
            int mExitAnim;
            int mPopEnterAnim;
            int mPopExitAnim;
            Lifecycle.State mOldMaxState;
            Lifecycle.State mCurrentMaxState;
    
            Op() {
            }
    
            Op(int cmd, Fragment fragment) {
                this.mCmd = cmd;   //状态
                this.mFragment = fragment;
                this.mOldMaxState = Lifecycle.State.RESUMED;
                this.mCurrentMaxState = Lifecycle.State.RESUMED;
            }
    
            Op(int cmd, @NonNull Fragment fragment, Lifecycle.State state) {
                this.mCmd = cmd;
                this.mFragment = fragment;
                this.mOldMaxState = fragment.mMaxState;
                this.mCurrentMaxState = state;
            }
        }
    

    相关文章

      网友评论

          本文标题:Fragment(一)

          本文链接:https://www.haomeiwen.com/subject/mxiuzltx.html