Fragment 源码分析

286 阅读7分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

框架的类图

image.png

  • FragmentActivity 是 Activity 支持 Fragment 的基础,

  • FragmentController是 FragmentActivity 和 FragmentManager 的中间桥接者,对 Fragment 的操作最终是分发到 FragmentManager 来处理;

  • FragmentManager负责对 Fragment 执行添加、移除或替换等操作,以及添加到返回堆栈。它的实现类 FragmentManagerImpl 是我们主要的分析对象;

  • FragmentHostCallback 是 FragmentManager 向 Fragment 宿主的回调接口

  • FragmentTransaction 是 Fragment 事务抽象类,它的实现类 BackStackRecord 是事务管理的主要分析对象。

生命周期

Fragment的几种状态
static final int INITIALIZING = 0;//初始状态,Fragment 未创建
static final int CREATED = 1;//已创建状态,Fragment 视图未创建
static final int ACTIVITY_CREATED = 2;//视图创建状态,Fragment 不可见
static final int STARTED = 3;//可见状态,Fragment 不处于前台
static final int RESUMED = 4;//前台状态,可接受用户交互
从FragmentActivity的oncreate中寻找生命周期的影子
protected void onCreate(@Nullable Bundle savedInstanceState) {
    this.mFragments.attachHost((Fragment)null);
    super.onCreate(savedInstanceState);
    FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
    if (nc != null && nc.viewModelStore != null && this.mViewModelStore == null) {
        this.mViewModelStore = nc.viewModelStore;
    }

    if (savedInstanceState != null) {
        Parcelable p = savedInstanceState.getParcelable("android:support:fragments");
        this.mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
        if (savedInstanceState.containsKey("android:support:next_request_index")) {
            this.mNextCandidateRequestIndex = savedInstanceState.getInt("android:support:next_request_index");
            int[] requestCodes = savedInstanceState.getIntArray("android:support:request_indicies");
            String[] fragmentWhos = savedInstanceState.getStringArray("android:support:request_fragment_who");
            if (requestCodes != null && fragmentWhos != null && requestCodes.length == fragmentWhos.length) {
                this.mPendingFragmentActivityResults = new SparseArrayCompat(requestCodes.length);

                for(int i = 0; i < requestCodes.length; ++i) {
                    this.mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                }
            } else {
                Log.w("FragmentActivity", "Invalid requestCode mapping in savedInstanceState.");
            }
        }
    }

    if (this.mPendingFragmentActivityResults == null) {
        this.mPendingFragmentActivityResults = new SparseArrayCompat();
        this.mNextCandidateRequestIndex = 0;
    }

    this.mFragments.dispatchCreate();
}

进入FragmentController类的 dispatchCreate方法

public void dispatchCreate() {
    this.mHost.mFragmentManager.dispatchCreate();
}

mHost 是 FragmentHostCallback

private final FragmentHostCallback<?> mHost;

FragmentController类中有大量dispatch开头的生命周期方法,所有的方法最后都会走到 dispatchStateChange方法中。

private void dispatchStateChange(int nextState) {
    try {
        this.mExecutingActions = true;
        this.moveToState(nextState, false);
    } finally {
        this.mExecutingActions = false;
    }

    this.execPendingActions();
}

进入moveToState方法

void moveToState(int newState, boolean always) {
    if (this.mHost == null && newState != 0) {
        throw new IllegalStateException("No activity");
    } else if (always || newState != this.mCurState) {
        this.mCurState = newState;
        if (this.mActive != null) {
            //mAdded 会将使用过的fragment都添加到集合中
            int numAdded = this.mAdded.size();

            int numActive;
            for(numActive = 0; numActive < numAdded; ++numActive) {
                Fragment f = (Fragment)this.mAdded.get(numActive);
               //移动fragment到期望状态
               this.moveFragmentToExpectedState(f);
            }

            numActive = this.mActive.size();

            for(int i = 0; i < numActive; ++i) {
                Fragment f = (Fragment)this.mActive.valueAt(i);
                if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                   //移动fragment到期望状态
                    this.moveFragmentToExpectedState(f);
                }
            }

            this.startPendingDeferredFragments();
            if (this.mNeedMenuInvalidate && this.mHost != null && this.mCurState == 4) {
                this.mHost.onSupportInvalidateOptionsMenu();
                this.mNeedMenuInvalidate = false;
            }
        }

    }
}

进入moveFragmentToExpectedState 方法

void moveFragmentToExpectedState(Fragment f) {
    if (f != null) {
        int nextState = this.mCurState;
        if (f.mRemoving) {
            if (f.isInBackStack()) {
                nextState = Math.min(nextState, 1);
            } else {
                nextState = Math.min(nextState, 0);
            }
        }

        this.moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
        if (f.mView != null) {
            Fragment underFragment = this.findFragmentUnder(f);
            if (underFragment != null) {
                View underView = underFragment.mView;
                ViewGroup container = f.mContainer;
                int underIndex = container.indexOfChild(underView);
                int viewIndex = container.indexOfChild(f.mView);
                if (viewIndex < underIndex) {
                    container.removeViewAt(viewIndex);
                    container.addView(f.mView, underIndex);
                }
            }

            if (f.mIsNewlyAdded && f.mContainer != null) {
                if (f.mPostponedAlpha > 0.0F) {
                    f.mView.setAlpha(f.mPostponedAlpha);
                }

                f.mPostponedAlpha = 0.0F;
                f.mIsNewlyAdded = false;
                FragmentManagerImpl.AnimationOrAnimator anim = this.loadAnimation(f, f.getNextTransition(), true, f.getNextTransitionStyle());
                if (anim != null) {
                    setHWLayerAnimListenerIfAlpha(f.mView, anim);
                    if (anim.animation != null) {
                        f.mView.startAnimation(anim.animation);
                    } else {
                        anim.animator.setTarget(f.mView);
                        anim.animator.start();
                    }
                }
            }
        }

        if (f.mHiddenChanged) {
            this.completeShowHideFragment(f);
        }

    }
}
进入moveToState方法(终于要开始进入生命周期的方法)
void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) {
    if ((!f.mAdded || f.mDetached) && newState > 1) {
        newState = 1;
    }

    if (f.mRemoving && newState > f.mState) {
        if (f.mState == 0 && f.isInBackStack()) {
            newState = 1;
        } else {
            newState = f.mState;
        }
    }

    if (f.mDeferStart && f.mState < 3 && newState > 2) {
        newState = 2;
    }

    if (f.mState <= newState) {
        label297: {
            if (f.mFromLayout && !f.mInLayout) {
                return;
            }
            if (f.getAnimatingAway() != null || f.getAnimator() != null) {
                f.setAnimatingAway((View)null);
                f.setAnimator((Animator)null);
                this.moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
            }
            switch(f.mState) {
            case 0:
                if (newState > 0) {
                    if (DEBUG) {
                        Log.v("FragmentManager", "moveto CREATED: " + f);
                    }

                    if (f.mSavedFragmentState != null) {
                        f.mSavedFragmentState.setClassLoader(this.mHost.getContext().getClassLoader());
                        f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray("android:view_state");
                        f.mTarget = this.getFragment(f.mSavedFragmentState, "android:target_state");
                        if (f.mTarget != null) {
                            f.mTargetRequestCode = f.mSavedFragmentState.getInt("android:target_req_state", 0);
                        }

                        if (f.mSavedUserVisibleHint != null) {
                            f.mUserVisibleHint = f.mSavedUserVisibleHint;
                            f.mSavedUserVisibleHint = null;
                        } else {
                            f.mUserVisibleHint = f.mSavedFragmentState.getBoolean("android:user_visible_hint", true);
                        }

                        if (!f.mUserVisibleHint) {
                            f.mDeferStart = true;
                            if (newState > 2) {
                                newState = 2;
                            }
                        }
                    }

                    f.mHost = this.mHost;
                    f.mParentFragment = this.mParent;
                    f.mFragmentManager = this.mParent != null ? this.mParent.mChildFragmentManager : this.mHost.getFragmentManagerImpl();
                    if (f.mTarget != null) {
                        if (this.mActive.get(f.mTarget.mIndex) != f.mTarget) {
                            throw new IllegalStateException("Fragment " + f + " declared target fragment " + f.mTarget + " that does not belong to this FragmentManager!");
                        }

                        if (f.mTarget.mState < 1) {
                            this.moveToState(f.mTarget, 1, 0, 0, true);
                        }
                    }

                    this.dispatchOnFragmentPreAttached(f, this.mHost.getContext(), false);
                    f.mCalled = false;
                    f.onAttach(this.mHost.getContext());
                    if (!f.mCalled) {
                        throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()");
                    }

                    if (f.mParentFragment == null) {
                        this.mHost.onAttachFragment(f);
                    } else {
                        f.mParentFragment.onAttachFragment(f);
                    }
                    //分发
                    this.dispatchOnFragmentAttached(f, this.mHost.getContext(), false);
                    //如果还没有创建
                    if (!f.mIsCreated) {
                        this.dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                        f.performCreate(f.mSavedFragmentState);
                        this.dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                    } else {
                        f.restoreChildFragmentState(f.mSavedFragmentState);
                        f.mState = 1;
                    }

                    f.mRetaining = false;
                }
            case 1:
                this.ensureInflatedFragmentView(f);
                if (newState > 1) {
                    if (DEBUG) {
                        Log.v("FragmentManager", "moveto ACTIVITY_CREATED: " + f);
                    }

                    if (!f.mFromLayout) {
                        ViewGroup container = null;
                        if (f.mContainerId != 0) {
                            if (f.mContainerId == -1) {
                                this.throwException(new IllegalArgumentException("Cannot create fragment " + f + " for a container view with no id"));
                            }

                            container = (ViewGroup)this.mContainer.onFindViewById(f.mContainerId);
                            if (container == null && !f.mRestored) {
                                String resName;
                                try {
                                    resName = f.getResources().getResourceName(f.mContainerId);
                                } catch (NotFoundException var9) {
                                    resName = "unknown";
                                }

                                this.throwException(new IllegalArgumentException("No view found for id 0x" + Integer.toHexString(f.mContainerId) + " (" + resName + ") for fragment " + f));
                            }
                        }

                        f.mContainer = container;
                        f.performCreateView(f.performGetLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);
                        if (f.mView == null) {
                            f.mInnerView = null;
                        } else {
                            f.mInnerView = f.mView;
                            f.mView.setSaveFromParentEnabled(false);
                            if (container != null) {
                                container.addView(f.mView);
                            }

                            if (f.mHidden) {
                                f.mView.setVisibility(8);
                            }

                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                            this.dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
                            f.mIsNewlyAdded = f.mView.getVisibility() == 0 && f.mContainer != null;
                        }
                    }

                    f.performActivityCreated(f.mSavedFragmentState);
                    this.dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                    if (f.mView != null) {
                        f.restoreViewState(f.mSavedFragmentState);
                    }

                    f.mSavedFragmentState = null;
                }
            case 2:
                if (newState > 2) {
                    if (DEBUG) {
                        Log.v("FragmentManager", "moveto STARTED: " + f);
                    }

                    f.performStart();
                    this.dispatchOnFragmentStarted(f, false);
                }
            case 3:
                break;
            default:
                break label297;
            }

            if (newState > 3) {
                if (DEBUG) {
                    Log.v("FragmentManager", "moveto RESUMED: " + f);
                }

                f.performResume();
                this.dispatchOnFragmentResumed(f, false);
                f.mSavedFragmentState = null;
                f.mSavedViewState = null;
            }
        }
    } else if (f.mState > newState) {
        switch(f.mState) {
        case 4:
            if (newState < 4) {
                if (DEBUG) {
                    Log.v("FragmentManager", "movefrom RESUMED: " + f);
                }

                f.performPause();
                this.dispatchOnFragmentPaused(f, false);
            }
        case 3:
            if (newState < 3) {
                if (DEBUG) {
                    Log.v("FragmentManager", "movefrom STARTED: " + f);
                }

                f.performStop();
                this.dispatchOnFragmentStopped(f, false);
            }
        case 2:
            if (newState < 2) {
                if (DEBUG) {
                    Log.v("FragmentManager", "movefrom ACTIVITY_CREATED: " + f);
                }

                if (f.mView != null && this.mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                    this.saveFragmentViewState(f);
                }

                f.performDestroyView();
                this.dispatchOnFragmentViewDestroyed(f, false);
                if (f.mView != null && f.mContainer != null) {
                    f.mContainer.endViewTransition(f.mView);
                    f.mView.clearAnimation();
                    FragmentManagerImpl.AnimationOrAnimator anim = null;
                    if (this.mCurState > 0 && !this.mDestroyed && f.mView.getVisibility() == 0 && f.mPostponedAlpha >= 0.0F) {
                        anim = this.loadAnimation(f, transit, false, transitionStyle);
                    }

                    f.mPostponedAlpha = 0.0F;
                    if (anim != null) {
                        this.animateRemoveFragment(f, anim, newState);
                    }

                    f.mContainer.removeView(f.mView);
                }

                f.mContainer = null;
                f.mView = null;
                f.mViewLifecycleOwner = null;
                f.mViewLifecycleOwnerLiveData.setValue((Object)null);
                f.mInnerView = null;
                f.mInLayout = false;
            }
        case 1:
            if (newState < 1) {
                if (this.mDestroyed) {
                    if (f.getAnimatingAway() != null) {
                        View v = f.getAnimatingAway();
                        f.setAnimatingAway((View)null);
                        v.clearAnimation();
                    } else if (f.getAnimator() != null) {
                        Animator animator = f.getAnimator();
                        f.setAnimator((Animator)null);
                        animator.cancel();
                    }
                }

                if (f.getAnimatingAway() == null && f.getAnimator() == null) {
                    if (DEBUG) {
                        Log.v("FragmentManager", "movefrom CREATED: " + f);
                    }

                    if (!f.mRetaining) {
                        f.performDestroy();
                        this.dispatchOnFragmentDestroyed(f, false);
                    } else {
                        f.mState = 0;
                    }

                    f.performDetach();
                    this.dispatchOnFragmentDetached(f, false);
                    if (!keepActive) {
                        if (!f.mRetaining) {
                            this.makeInactive(f);
                        } else {
                            f.mHost = null;
                            f.mParentFragment = null;
                            f.mFragmentManager = null;
                        }
                    }
                } else {
                    f.setStateAfterAnimating(newState);
                    newState = 1;
                }
            }
        }
    }

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

}

第一次进入的时候,执行 f.onAttach(this.mHost.getContext());

public void onAttach(Context context) {
    this.mCalled = true;
    Activity hostActivity = this.mHost == null ? null : this.mHost.getActivity();
    if (hostActivity != null) {
        this.mCalled = false;
        this.onAttach(hostActivity);
    }

}

onAttach执行完之后就进入dispatchOnFragmentAttached方法

void dispatchOnFragmentAttached(@NonNull Fragment f, @NonNull Context context, boolean onlyRecursive) {
    if (this.mParent != null) {
       //获取父类的FragmentManager
        FragmentManager parentManager = this.mParent.getFragmentManager();
        if (parentManager instanceof FragmentManagerImpl) {
            ((FragmentManagerImpl)parentManager).dispatchOnFragmentAttached(f, context, true);
        }
    }

    Iterator var6 = this.mLifecycleCallbacks.iterator();

    while(true) {
        FragmentManagerImpl.FragmentLifecycleCallbacksHolder holder;
        do {
            if (!var6.hasNext()) {
                return;
            }

            holder = (FragmentManagerImpl.FragmentLifecycleCallbacksHolder)var6.next();
        } while(onlyRecursive && !holder.mRecursive);

        holder.mCallback.onFragmentAttached(this, f, context);
    }
}

继续执行,如果还没有创建的话会执行performCreate(f.mSavedFragmentState)方法

void performCreate(Bundle savedInstanceState) {
    if (this.mChildFragmentManager != null) {
        this.mChildFragmentManager.noteStateNotSaved();
    }
    //把状态变成create,目的是下一个case能够进入方法
    this.mState = 1;
    this.mCalled = false;
    //回掉onCreate 方法
    this.onCreate(savedInstanceState);
    this.mIsCreated = true;
    if (!this.mCalled) {
        throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onCreate()");
    } else {
        this.mLifecycleRegistry.handleLifecycleEvent(Event.ON_CREATE);
    }
}

会回掉oncreate方法。

进入create状态

会执行performCreateView 方法

f.performCreateView(f.performGetLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);

进入performCreateView方法

void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    if (this.mChildFragmentManager != null) {
        this.mChildFragmentManager.noteStateNotSaved();
    }

    this.mPerformedCreateView = true;
    this.mViewLifecycleOwner = new LifecycleOwner() {
        public Lifecycle getLifecycle() {
            if (Fragment.this.mViewLifecycleRegistry == null) {
                Fragment.this.mViewLifecycleRegistry = new LifecycleRegistry(Fragment.this.mViewLifecycleOwner);
            }

            return Fragment.this.mViewLifecycleRegistry;
        }
    };
    this.mViewLifecycleRegistry = null;
    //创建view
    this.mView = this.onCreateView(inflater, container, savedInstanceState);
    if (this.mView != null) {
        this.mViewLifecycleOwner.getLifecycle();
        this.mViewLifecycleOwnerLiveData.setValue(this.mViewLifecycleOwner);
    } else {
        if (this.mViewLifecycleRegistry != null) {
            throw new IllegalStateException("Called getViewLifecycleOwner() but onCreateView() returned null");
        }

        this.mViewLifecycleOwner = null;
    }

}

执行完之后View就已经被创建出来了。

继续往下执行会有一个performActivityCreated(f.mSavedFragmentState)被调用

void performActivityCreated(Bundle savedInstanceState) {
    if (this.mChildFragmentManager != null) {
        this.mChildFragmentManager.noteStateNotSaved();
    }
    //将状态赋值
    this.mState = 2;
    this.mCalled = false;
    this.onActivityCreated(savedInstanceState);
    if (!this.mCalled) {
        throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onActivityCreated()");
    } else {
        if (this.mChildFragmentManager != null) {
            this.mChildFragmentManager.dispatchActivityCreated();
        }

    }
}

执行onActivityCreated方法

状态为ACTIVITY_CREATED继续执行代码 执行f.performStart();

void performStart() {
    if (this.mChildFragmentManager != null) {
        this.mChildFragmentManager.noteStateNotSaved();
        this.mChildFragmentManager.execPendingActions();
    }
    //修改状态的值
    this.mState = 3;
    this.mCalled = false;
    this.onStart();
    if (!this.mCalled) {
        throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onStart()");
    } else {
        if (this.mChildFragmentManager != null) {
            this.mChildFragmentManager.dispatchStart();
        }

        this.mLifecycleRegistry.handleLifecycleEvent(Event.ON_START);
        if (this.mView != null) {
            this.mViewLifecycleRegistry.handleLifecycleEvent(Event.ON_START);
        }

    }
}

执行onStart()方法

状态为STARTED,继续往下,执行f.performResume()方法

void performResume() {
    if (this.mChildFragmentManager != null) {
        this.mChildFragmentManager.noteStateNotSaved();
        this.mChildFragmentManager.execPendingActions();
    }
    //给状态赋值
    this.mState = 4;
    this.mCalled = false;
    this.onResume();
    if (!this.mCalled) {
        throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onResume()");
    } else {
        if (this.mChildFragmentManager != null) {
            this.mChildFragmentManager.dispatchResume();
            this.mChildFragmentManager.execPendingActions();
        }

        this.mLifecycleRegistry.handleLifecycleEvent(Event.ON_RESUME);
        if (this.mView != null) {
            this.mViewLifecycleRegistry.handleLifecycleEvent(Event.ON_RESUME);
        }

    }
}

执行onResume的生命周期的方法。

至此fragment就已经显示出来了。

fragment退出时会执行下面的代码

else if (f.mState > newState) {
    switch(f.mState) {
    case 4:
        if (newState < 4) {
            if (DEBUG) {
                Log.v("FragmentManager", "movefrom RESUMED: " + f);
            }

            f.performPause();
            this.dispatchOnFragmentPaused(f, false);
        }
    case 3:
        if (newState < 3) {
            if (DEBUG) {
                Log.v("FragmentManager", "movefrom STARTED: " + f);
            }

            f.performStop();
            this.dispatchOnFragmentStopped(f, false);
        }
    case 2:
        if (newState < 2) {
            if (DEBUG) {
                Log.v("FragmentManager", "movefrom ACTIVITY_CREATED: " + f);
            }

            if (f.mView != null && this.mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                this.saveFragmentViewState(f);
            }

            f.performDestroyView();
            this.dispatchOnFragmentViewDestroyed(f, false);
            if (f.mView != null && f.mContainer != null) {
                f.mContainer.endViewTransition(f.mView);
                f.mView.clearAnimation();
                FragmentManagerImpl.AnimationOrAnimator anim = null;
                if (this.mCurState > 0 && !this.mDestroyed && f.mView.getVisibility() == 0 && f.mPostponedAlpha >= 0.0F) {
                    anim = this.loadAnimation(f, transit, false, transitionStyle);
                }

                f.mPostponedAlpha = 0.0F;
                if (anim != null) {
                    this.animateRemoveFragment(f, anim, newState);
                }

                f.mContainer.removeView(f.mView);
            }

            f.mContainer = null;
            f.mView = null;
            f.mViewLifecycleOwner = null;
            f.mViewLifecycleOwnerLiveData.setValue((Object)null);
            f.mInnerView = null;
            f.mInLayout = false;
        }
    case 1:
        if (newState < 1) {
            if (this.mDestroyed) {
                if (f.getAnimatingAway() != null) {
                    View v = f.getAnimatingAway();
                    f.setAnimatingAway((View)null);
                    v.clearAnimation();
                } else if (f.getAnimator() != null) {
                    Animator animator = f.getAnimator();
                    f.setAnimator((Animator)null);
                    animator.cancel();
                }
            }

            if (f.getAnimatingAway() == null && f.getAnimator() == null) {
                if (DEBUG) {
                    Log.v("FragmentManager", "movefrom CREATED: " + f);
                }

                if (!f.mRetaining) {
                    f.performDestroy();
                    this.dispatchOnFragmentDestroyed(f, false);
                } else {
                    f.mState = 0;
                }

                f.performDetach();
                this.dispatchOnFragmentDetached(f, false);
                if (!keepActive) {
                    if (!f.mRetaining) {
                        this.makeInactive(f);
                    } else {
                        f.mHost = null;
                        f.mParentFragment = null;
                        f.mFragmentManager = null;
                    }
                }
            } else {
                f.setStateAfterAnimating(newState);
                newState = 1;
            }
        }
    }
}

依次调用: f.performPause() -》this.onPause() -》f.performStop() -》 this.onStop() -》f.performDestroyView() -》this.onDestroyView() -》f.performDestroy()-》this.onDestroy()

自此fragment的生命周期的大致流程就走过路一遍。

小结

fragment_lifecycle.png

常见操作

添加操作
  FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
       transaction.add(XXXX)
       transaction.commit()

进入add方法

public FragmentTransaction add(int containerViewId, Fragment fragment, @Nullable String tag) {
    this.doAddOp(containerViewId, fragment, tag, 1);
    return this;
}

进入doAddOp方法

private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
    Class fragmentClass = fragment.getClass();
    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.");
    } else {
        fragment.mFragmentManager = this.mManager;
        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 == -1) {
                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;
        }

        this.addOp(new BackStackRecord.Op(opcmd, fragment));
    }
}

Op类的相关介绍

static final class Op {
    int cmd;
    Fragment fragment;
    int enterAnim;
    int exitAnim;
    int popEnterAnim;
    int popExitAnim;

    Op() {
    }

    Op(int cmd, Fragment fragment) {
        this.cmd = cmd;
        this.fragment = fragment;
    }
}

进入addOp 方法

void addOp(BackStackRecord.Op op) {
    this.mOps.add(op);
    op.enterAnim = this.mEnterAnim;
    op.exitAnim = this.mExitAnim;
    op.popEnterAnim = this.mPopEnterAnim;
    op.popExitAnim = this.mPopExitAnim;
}

commit提交

public int commit() {
    return this.commitInternal(false);//状态不掉时
}

进入commitInternal方法

int commitInternal(boolean allowStateLoss) {
    if (this.mCommitted) {
        throw new IllegalStateException("commit already called");
    } else {
        if (FragmentManagerImpl.DEBUG) {
            Log.v("FragmentManager", "Commit: " + this);
            LogWriter logw = new LogWriter("FragmentManager");
            PrintWriter pw = new PrintWriter(logw);
            this.dump("  ", (FileDescriptor)null, pw, (String[])null);
            pw.close();
        }
        //提交完成
        this.mCommitted = true;
        //是否存在栈操作
        if (this.mAddToBackStack) {
            this.mIndex = this.mManager.allocBackStackIndex(this);
        } else {
            this.mIndex = -1;
        }

        this.mManager.enqueueAction(this, allowStateLoss);
        return this.mIndex;
    }
}

进入enqueueAction方法

public void enqueueAction(FragmentManagerImpl.OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        this.checkStateLoss();
    }

    synchronized(this) {
        if (!this.mDestroyed && this.mHost != null) {
            if (this.mPendingActions == null) {
                this.mPendingActions = new ArrayList();
            }
            //添加到存放事物操作的集合
            this.mPendingActions.add(action);
            //执行提交
            this.scheduleCommit();
        } else if (!allowStateLoss) {
            throw new IllegalStateException("Activity has been destroyed");
        }
    }
}

scheduleCommit执行提交

void scheduleCommit() {
    synchronized(this) {
        boolean postponeReady = this.mPostponedTransactions != null && !this.mPostponedTransactions.isEmpty();
        boolean pendingReady = this.mPendingActions != null && this.mPendingActions.size() == 1;
        if (postponeReady || pendingReady) {
            this.mHost.getHandler().removeCallbacks(this.mExecCommit);
            this.mHost.getHandler().post(this.mExecCommit);
        }

    }
}

mExecCommit是一个Runnable对象,里面执行execPendingActions方法

Runnable mExecCommit = new Runnable() {
    public void run() {
        FragmentManagerImpl.this.execPendingActions();
    }
};

执行execPendingActions方法

public boolean execPendingActions() {
    this.ensureExecReady(true);
    boolean didSomething;
    for(didSomething = false; this.generateOpsForPendingActions(this.mTmpRecords, this.mTmpIsPop); didSomething = true) {
        this.mExecutingActions = true;

        try {
           //裁剪操作 this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
        } finally {
            this.cleanupExec();
        }
    }
    this.doPendingDeferredStart();
    this.burpActive();
    return didSomething;
}

generateOpsForPendingActions()这个方法是重新组装一下数据,添加一个是否放入栈的标签。

进入removeRedundantOperationsAndExecute方法

private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
    if (records != null && !records.isEmpty()) {
        if (isRecordPop != null && records.size() == isRecordPop.size()) {
            this.executePostponedTransaction(records, isRecordPop);
            int numRecords = records.size();
            int startIndex = 0;

            for(int recordNum = 0; recordNum < numRecords; ++recordNum) {
                boolean canReorder = ((BackStackRecord)records.get(recordNum)).mReorderingAllowed;
                if (!canReorder) {
                    if (startIndex != recordNum) {
                        //执行操作
                        this.executeOpsTogether(records, isRecordPop, startIndex, recordNum);
                    }
                    int reorderingEnd = recordNum + 1;
                    if ((Boolean)isRecordPop.get(recordNum)) {
                        while(reorderingEnd < numRecords && (Boolean)isRecordPop.get(reorderingEnd) && !((BackStackRecord)records.get(reorderingEnd)).mReorderingAllowed) {
                            ++reorderingEnd;
                        }
                    }

                    this.executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
                    startIndex = reorderingEnd;
                    recordNum = reorderingEnd - 1;
                }
            }
            if (startIndex != numRecords) {
                this.executeOpsTogether(records, isRecordPop, startIndex, numRecords);
            }
        } else {
            throw new IllegalStateException("Internal error with the back stack records");
        }
    }
}

进入executeOpsTogether方法

private void executeOpsTogether(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    boolean allowReordering = ((BackStackRecord)records.get(startIndex)).mReorderingAllowed;
    boolean addToBackStack = false;
    if (this.mTmpAddedFragments == null) {
        this.mTmpAddedFragments = new ArrayList();
    } else {
        this.mTmpAddedFragments.clear();
    }

    this.mTmpAddedFragments.addAll(this.mAdded);
    Fragment oldPrimaryNav = this.getPrimaryNavigationFragment();

    int postponeIndex;
    for(postponeIndex = startIndex; postponeIndex < endIndex; ++postponeIndex) {
        BackStackRecord record = (BackStackRecord)records.get(postponeIndex);
        boolean isPop = (Boolean)isRecordPop.get(postponeIndex);
        if (!isPop) {
            oldPrimaryNav = record.expandOps(this.mTmpAddedFragments, oldPrimaryNav);
        } else {
            oldPrimaryNav = record.trackAddedFragmentsInPop(this.mTmpAddedFragments, oldPrimaryNav);
        }

        addToBackStack = addToBackStack || record.mAddToBackStack;
    }

    this.mTmpAddedFragments.clear();
    if (!allowReordering) {
        FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex, false);
    }

    executeOps(records, isRecordPop, startIndex, endIndex);
    postponeIndex = endIndex;
    if (allowReordering) {
        ArraySet<Fragment> addedFragments = new ArraySet();
        this.addAddedFragments(addedFragments);
        postponeIndex = this.postponePostponableTransactions(records, isRecordPop, startIndex, endIndex, addedFragments);
        this.makeRemovedFragmentsInvisible(addedFragments);
    }

    if (postponeIndex != startIndex && allowReordering) {
        FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, postponeIndex, true);
        this.moveToState(this.mCurState, true);
    }

    for(int recordNum = startIndex; recordNum < endIndex; ++recordNum) {
        BackStackRecord record = (BackStackRecord)records.get(recordNum);
        boolean isPop = (Boolean)isRecordPop.get(recordNum);
        if (isPop && record.mIndex >= 0) {
            this.freeBackStackIndex(record.mIndex);
            record.mIndex = -1;
        }

        record.runOnCommitRunnables();
    }

    if (addToBackStack) {
        this.reportBackStackChanged();
    }

}

进入expandOps方法

Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
    for(int opNum = 0; opNum < this.mOps.size(); ++opNum) {
        BackStackRecord.Op op = (BackStackRecord.Op)this.mOps.get(opNum);
        switch(op.cmd) {
        case 1:
        case 7:
            added.add(op.fragment);
            break;
        case 2:
            Fragment f = op.fragment;
            int containerId = f.mContainerId;
            boolean alreadyAdded = false;
            int i = added.size() - 1;

            for(; i >= 0; --i) {
                Fragment old = (Fragment)added.get(i);
                if (old.mContainerId == containerId) {
                    if (old == f) {
                        alreadyAdded = true;
                    } else {
                        if (old == oldPrimaryNav) {
                            this.mOps.add(opNum, new BackStackRecord.Op(9, old));
                            ++opNum;
                            oldPrimaryNav = null;
                        }

                        BackStackRecord.Op removeOp = new BackStackRecord.Op(3, old);
                        removeOp.enterAnim = op.enterAnim;
                        removeOp.popEnterAnim = op.popEnterAnim;
                        removeOp.exitAnim = op.exitAnim;
                        removeOp.popExitAnim = op.popExitAnim;
                        this.mOps.add(opNum, removeOp);
                        added.remove(old);
                        ++opNum;
                    }
                }
            }

            if (alreadyAdded) {
                this.mOps.remove(opNum);
                --opNum;
            } else {
                op.cmd = 1;
                added.add(f);
            }
            break;
        case 3:
        case 6:
            added.remove(op.fragment);
            if (op.fragment == oldPrimaryNav) {
                this.mOps.add(opNum, new BackStackRecord.Op(9, op.fragment));
                ++opNum;
                oldPrimaryNav = null;
            }
        case 4:
        case 5:
        default:
            break;
        case 8:
            this.mOps.add(opNum, new BackStackRecord.Op(9, oldPrimaryNav));
            ++opNum;
            oldPrimaryNav = op.fragment;
        }
    }

    return oldPrimaryNav;
}

所有的操作都变成路add操作

继续往下,进入executeOps方法

private static void executeOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    //循环取事物
    for(int i = startIndex; i < endIndex; ++i) {
        BackStackRecord record = (BackStackRecord)records.get(i);
        boolean isPop = (Boolean)isRecordPop.get(i);
        if (isPop) {
            record.bumpBackStackNesting(-1);
            boolean moveToState = i == endIndex - 1;
            record.executePopOps(moveToState);
        } else {
            record.bumpBackStackNesting(1);
            record.executeOps();
        }
    }

}

进入executeOps 方法

void executeOps() {
    int numOps = this.mOps.size();

    for(int opNum = 0; opNum < numOps; ++opNum) {
        BackStackRecord.Op op = (BackStackRecord.Op)this.mOps.get(opNum);
        Fragment f = op.fragment;
        if (f != null) {
            f.setNextTransition(this.mTransition, this.mTransitionStyle);
        }

        switch(op.cmd) {
        case 1:
            f.setNextAnim(op.enterAnim);
            this.mManager.addFragment(f, false);
            break;
        case 2:
        default:
            throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
        case 3:
            f.setNextAnim(op.exitAnim);
            this.mManager.removeFragment(f);
            break;
        case 4:
            f.setNextAnim(op.exitAnim);
            this.mManager.hideFragment(f);
            break;
        case 5:
            f.setNextAnim(op.enterAnim);
            this.mManager.showFragment(f);
            break;
        case 6:
            f.setNextAnim(op.exitAnim);
            this.mManager.detachFragment(f);
            break;
        case 7:
            f.setNextAnim(op.enterAnim);
            this.mManager.attachFragment(f);
            break;
        case 8:
            this.mManager.setPrimaryNavigationFragment(f);
            break;
        case 9:
            this.mManager.setPrimaryNavigationFragment((Fragment)null);
        }

        if (!this.mReorderingAllowed && op.cmd != 1 && f != null) {
            this.mManager.moveFragmentToExpectedState(f);
        }
    }

    if (!this.mReorderingAllowed) {
        this.mManager.moveToState(this.mManager.mCurState, true);
    }

}

找一个添加Fragment的方法分析一下

public void addFragment(Fragment fragment, boolean moveToStateNow) {
    if (DEBUG) {
        Log.v("FragmentManager", "add: " + fragment);
    }

    this.makeActive(fragment);
    if (!fragment.mDetached) {//没有销毁
        if (this.mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }

        synchronized(this.mAdded) {
            this.mAdded.add(fragment);//添加到可用集合
        }

        fragment.mAdded = true;
        fragment.mRemoving = false;
        if (fragment.mView == null) {
            fragment.mHiddenChanged = false;
        }

        if (fragment.mHasMenu && fragment.mMenuVisible) {
            this.mNeedMenuInvalidate = true;
        }

        if (moveToStateNow) {
            this.moveToState(fragment);//走生命周期的方法
        }
    }

}

到此添加的操作基本算走完。

常见的OP的值

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;
小结

remove,replace,hide,show 和add有点类似,所以暂时不做分析。

image.png

回退栈

public FragmentTransaction addToBackStack(@Nullable String name) {
    if (!this.mAllowAddToBackStack) {
        throw new IllegalStateException("This FragmentTransaction is not allowed to be added to the back stack.");
    } else {
       //设置一个标签
        this.mAddToBackStack = true;
        this.mName = name;
        return this;
    }
}

提交的时候

int commitInternal(boolean allowStateLoss) {
    if (this.mCommitted) {
        throw new IllegalStateException("commit already called");
    } else {
        if (FragmentManagerImpl.DEBUG) {
            Log.v("FragmentManager", "Commit: " + this);
            LogWriter logw = new LogWriter("FragmentManager");
            PrintWriter pw = new PrintWriter(logw);
            this.dump("  ", (FileDescriptor)null, pw, (String[])null);
            pw.close();
        }

        this.mCommitted = true;
        if (this.mAddToBackStack) {
            this.mIndex = this.mManager.allocBackStackIndex(this);
        } else {
            this.mIndex = -1;
        }

        this.mManager.enqueueAction(this, allowStateLoss);
        return this.mIndex;
    }
}

调用mManager.allocBackStackIndex(this);

public int allocBackStackIndex(BackStackRecord bse) {
    synchronized(this) {
        int index;
        if (this.mAvailBackStackIndices != null && this.mAvailBackStackIndices.size() > 0) {
            index = (Integer)this.mAvailBackStackIndices.remove(this.mAvailBackStackIndices.size() - 1);
            if (DEBUG) {
                Log.v("FragmentManager", "Adding back stack index " + index + " with " + bse);
            }

            this.mBackStackIndices.set(index, bse);
            return index;
        } else {
            if (this.mBackStackIndices == null) {
                this.mBackStackIndices = new ArrayList();
            }

            index = this.mBackStackIndices.size();
            if (DEBUG) {
                Log.v("FragmentManager", "Setting back stack index " + index + " to " + bse);
            }

            this.mBackStackIndices.add(bse);
            return index;
        }
    }
}

释放

public void freeBackStackIndex(int index) {
    synchronized(this) {
        this.mBackStackIndices.set(index, (Object)null);
        if (this.mAvailBackStackIndices == null) {
            this.mAvailBackStackIndices = new ArrayList();
        }

        if (DEBUG) {
            Log.v("FragmentManager", "Freeing back stack index " + index);
        }

        this.mAvailBackStackIndices.add(index);
    }
}

设置

public void setBackStackIndex(int index, BackStackRecord bse) {
    synchronized(this) {
        if (this.mBackStackIndices == null) {
            this.mBackStackIndices = new ArrayList();
        }

        int N = this.mBackStackIndices.size();
        if (index < N) {
            if (DEBUG) {
                Log.v("FragmentManager", "Setting back stack index " + index + " to " + bse);
            }

            this.mBackStackIndices.set(index, bse);
        } else {
            while(N < index) {
                this.mBackStackIndices.add((Object)null);
                if (this.mAvailBackStackIndices == null) {
                    this.mAvailBackStackIndices = new ArrayList();
                }

                if (DEBUG) {
                    Log.v("FragmentManager", "Adding available back stack index " + N);
                }

                this.mAvailBackStackIndices.add(N);
                ++N;
            }

            if (DEBUG) {
                Log.v("FragmentManager", "Adding back stack index " + index + " with " + bse);
            }

            this.mBackStackIndices.add(bse);
        }

    }
}

回退栈的原理:

image.png

首次添加fragment的时候先向mBackStackIndices添加,当时释放的时候会通过索引将mBackStackIndices位置设置为null,同时把索引存到mAvailBackStackIndices中,下次添加的时候先从mAvailBackStackIndices拿索引值,给mBackStackIndices对应的索引位置设置值

这样操作提高的内存的复用,避免频繁的创建。

常见面试题

怎么去管理Fragment?

通过getFragmentManager()方法获取FragmentManager实例 调用findFragmentById()或者findFragmentByTag()方法来获取一个Fragment 调用popBackStack方法将Fragment从后退站中弹出 调用addOnBackChangedListener()方法注册监听器,用于监听后退站的变化

执行Fragment的事务,事务有什么特点?

每个事务都表示执行一组变化,这些变化包括add()、remove()、replace()、addToBackStack()、setCustomAnimations、setTransition事务要生效必须调用commit,commit并不会立即执行,只能等待UI主线程空闲时才能执行也可以调用executePendingTransactions立即生效提交事务,commit在调用时机是Activity状态保存之前进行,也就是说如果在离开Activity是进行提交事务的操作,系统就会抛出异常

简述Fragment生命周期,常用的回调方法有几个?

onActtch:初始化Fragment 事件回调接口 onCreate:初始化参数 onCreateView:为Fragment绑定布局 onViewCreated:进行控件实例化操作 onPause:在用户离开Fragment是所进行的一些数据持久化操作 当Activity的onCreate方法被回调时会导致fragment方法的onAttach()、onCreate()、onCreateView()、onActivityCreate() 被连续回调

Activity和Fragment 的 onActivityForResult 回调?
  • 当在Fragment里面调用startActivityForResult的时候 Activity和Fragment里面的onActivityForResult都会回调,只不过Fragment里面回调的requestCode是正确的
  • 当在Fragment里面调用getActivity().startActivityForResult的时候,就会回调Activity里面的onActivityForResult
  • 当Fragment存在多层嵌套的情况,内层的Fragment调用startActivityForResult的时候,onActivityForResult方法不回调,此时需要创建一个BaseActivity复写它的onActivityResult方法
Fragment的getActivity方法返回null的原因:

如果系统内存不足、或者切换横竖屏、或者app长时间在后台运行,Activity都可能会被系统回收,但是Fragment并不会随着Activity的回收而被回收,从而导致Fragment丢失对应的Activity。这里,假设我们继承于FragmentActivity的类为MainActivity,其中用到的Fragment为FragmentA。 app发生的变化为:某种原因系统回收MainActivity——FragmentA被保存状态未被回收——再次点击app进入——首先加载的是未被回收的FragmentA的页面——由于MainActivity被回收,系统会重启MainActivity,FragmentA也会被再次加载——页面出现混乱,因为一层未回收的FragmentA覆盖在其上面——(假如FragmentA使用到了getActivity()方法)会报NullPointerException:

方案1:在使用Fragment的Activity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState)注释掉,让其不再保存Fragment的状态,达到其随着MainActivity一起被回收的效果。

方案2:在再次启动Activity的时候,在onCreate方法中将之前保存过的fragment状态清除

方案3:避免使用getActivity方法得到activity,如果确实需要使用上下文,可以写一个类MyApplication继承Application,并且写一个方法getContext(),返回一个Context 对象。

请简述Fragment的意义?
  • Fragment是Activity界面的一部分,Fragment是依附于Activity之上的;
  • Activity是Fragment的基础,Fragment是Activity的延续和发展
  • 一个Activity可以有多个Fragment,一个Fragment也可以被多个Activity重复使用;
  • 一个Fragment除了Activity处于onResume状态下,他可以自己灵活的控制自己的生命周期,其他状态下,其生命周期都是由Activity所决定的;
  • Fragment的出现增强了UI界面布局的灵活性,可以实现动态的改变UI布局;