android 中 Fragment 模块源码解析

Activity 中使用 Fragment,一般为了兼容3.0以下低版本,会继承 FragmentActivity,然后在layout布局中添加,或者在代码中动态添加

onCreate():
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    transaction.replace(id, fragment);
    transaction.commit();

我们看一下,getSupportFragmentManager() 对应的是

    FragmentActivity:
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
    }

HostCallbacks 是 FragmentActivity 中的内部类,继承了 FragmentHostCallback<FragmentActivity> ;我们看看 FragmentController 中代码

    private final FragmentHostCallback<?> mHost;
    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
    }
    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }
    public FragmentManager getSupportFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }
这里 FragmentHostCallback<?> 泛型中的类型是 FragmentActivity,上面有提到 HostCallbacks 继承了 FragmentHostCallback<FragmentActivity>;因此
mFragments.getSupportFragmentManager() 调用的是 FragmentController 中的 getSupportFragmentManager() 方法,即 mHost.getFragmentManagerImpl(),我们看看
HostCallbacks 的代码,它里面没这个方法,去它的父类 FragmentHostCallback 中找

    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }
我们看看 FragmentManagerImpl 是什么,它继承了 FragmentManager ,实现了接口 LayoutInflaterFactory,看名字也知道是一个具体逻辑管理的实现类,好家伙,仅仅一行代码,就嵌套了这么多层。

我们看第二行代码,FragmentTransaction transaction = fm.beginTransaction(); 开启一个事物,此时对应的是 FragmentManagerImpl 中的方法

    @Override
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }
这个事物管理器,就是 BackStackRecord,下一步, transaction.replace(id, fragment); 对应的则是

    public FragmentTransaction replace(int containerViewId, Fragment fragment) {
        return replace(containerViewId, fragment, null);
    }

    public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        }

        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;
        if (tag != null) {
            fragment.mTag = tag;
        }
        if (containerViewId != 0) {
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }
    
    void addOp(Op op) {
        if (mHead == null) {
            mHead = mTail = op;
        } else {
            op.prev = mTail;
            mTail.next = op;
            mTail = op;
        }
        op.enterAnim = mEnterAnim;
        op.exitAnim = mExitAnim;
        op.popEnterAnim = mPopEnterAnim;
        op.popExitAnim = mPopExitAnim;
        mNumOp++;
    }
    
创建了 Op op = new Op(); 对象,把当前fragment和 static final int OP_REPLACE = 2; 放置进去, Op 是一个数据结构容器,通过 addOp(op) 方法,可以看出,它是一个双链表,从前往后排。

最后看看 transaction.commit(); 提交事物,我们看看它的逻辑

    final FragmentManagerImpl mManager;
    public int commit() {
        return commitInternal(false);
    }
    int commitInternal(boolean allowStateLoss) {
        mCommitted = true;
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }
我们看看 FragmentManagerImpl 中的代码 enqueueAction 方法

    public void enqueueAction(Runnable action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<Runnable>();
            }
            mPendingActions.add(action);
            if (mPendingActions.size() == 1) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }

    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };
    public boolean execPendingActions() {
        boolean didSomething = false;
        while (true) {
            int numActions;
            synchronized (this) {
                if (mPendingActions == null || mPendingActions.size() == 0) {
                    break;
                }
                numActions = mPendingActions.size();
                if (mTmpActions == null || mTmpActions.length < numActions) {
                    mTmpActions = new Runnable[numActions];
                }
                mPendingActions.toArray(mTmpActions);
                mPendingActions.clear();
                mHost.getHandler().removeCallbacks(mExecCommit);
            }

            mExecutingActions = true;
            for (int i=0; i<numActions; i++) {
                mTmpActions[i].run();
                mTmpActions[i] = null;
            }
            mExecutingActions = false;
            didSomething = true;
        }

        if (mHavePendingDeferredStart) {
            boolean loadersRunning = false;
            for (int i=0; i<mActive.size(); i++) {
                Fragment f = mActive.get(i);
                if (f != null && f.mLoaderManager != null) {
                    loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                }
            }
            if (!loadersRunning) {
                mHavePendingDeferredStart = false;
                startPendingDeferredFragments();
            }
        }
        return didSomething;
    }
最终在主线程中执行 execPendingActions(); 方法,我们继续往里面看,enqueueAction() 方法中把 runnable 加入了mPendingActions集合中,execPendingActions() 中把它转换到mTmpActions 数组中,下面有个for循环方法,mTmpActions[i].run(); 这里执行了 runnable 的run() 方法,这个runnable是什么呢? enqueueAction(this, allowStateLoss)方法中把BackStackRecord 添加了进去,BackStackRecord 实现了 Runnable 接口,那么我们看看 run() 方法中的代码

    public void run() {
        ...
        Op op = mHead;
        while (op != null) {
            int enterAnim = state != null ? 0 : op.enterAnim;
            int exitAnim = state != null ? 0 : op.exitAnim;
            switch (op.cmd) {
                case OP_ADD: {
                    Fragment f = op.fragment;
                    f.mNextAnim = enterAnim;
                    mManager.addFragment(f, false);
                } break;
                case OP_REPLACE: {
                    Fragment f = op.fragment;
                    ...
                    if (f != null) {
                        f.mNextAnim = enterAnim;
                        mManager.addFragment(f, false);
                    }
                } break;
                case OP_REMOVE: {
                    Fragment f = op.fragment;
                    f.mNextAnim = exitAnim;
                    mManager.removeFragment(f, transition, transitionStyle);
                } break;
                ...
            }
            op = op.next;
        }
        mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);
        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
    }

这里是简化版的,会执行到 switch中的 case OP_REPLACE 方法中,先把添加到Activity中的Fragment给清除掉,然后调用 mManager.addFragment(f, false); 方法,这个方法中有集合维护添加到activity中的fragment,最后看 moveToState() 方法,这个是重点

    void moveToState(int newState, int transit, int transitStyle, boolean always) {
        if (mHost == null && newState != Fragment.INITIALIZING) {
            throw new IllegalStateException("No host");
        }

        if (!always && mCurState == newState) {
            return;
        }

        mCurState = newState;
        if (mActive != null) {
            boolean loadersRunning = false;
            for (int i=0; i<mActive.size(); i++) {
                Fragment f = mActive.get(i);
                if (f != null) {
                    moveToState(f, newState, transit, transitStyle, false);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }

            if (!loadersRunning) {
                startPendingDeferredFragments();
            }

            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                mHost.onSupportInvalidateOptionsMenu();
                mNeedMenuInvalidate = false;
            }
        }
    }
这个方法中会更新 mCurState 值,先记住这一点。由于 addFragment() 时已经把fragment添加到  mActive 集合中,此时会执行moveToState(f, newState, transit, transitStyle,false) 方法,注意注意注意,真正的重点

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
        ...
        if (f.mState < newState) {
            ...
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    ...
                    f.mHost = mHost;
                    f.mParentFragment = mParent;
                    f.mFragmentManager = mParent != null
                            ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                    f.mCalled = false;
                    f.onAttach(mHost.getContext());
                    if (!f.mCalled) {
                        throw new SuperNotCalledException("Fragment " + f
                                + " did not call through to super.onAttach()");
                    }
                    if (f.mParentFragment == null) {
                        mHost.onAttachFragment(f);
                    }

                    if (!f.mRetaining) {
                        f.performCreate(f.mSavedFragmentState);
                    }
                    f.mRetaining = false;
                    if (f.mFromLayout) {
                        ...
                    }
                case Fragment.CREATED:
                    if (newState > Fragment.CREATED) {
                        if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                        if (!f.mFromLayout) {
                            ViewGroup container = null;
                            if (f.mContainerId != 0) {
                                container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
                            }
                            f.mContainer = container;
                            f.mView = f.performCreateView(f.getLayoutInflater(
                                    f.mSavedFragmentState), container, f.mSavedFragmentState);
                            if (f.mView != null) {
                                f.mInnerView = f.mView;
                                if (container != null) {
                                    Animation anim = loadAnimation(f, transit, true,
                                            transitionStyle);
                                    if (anim != null) {
                                        setHWLayerAnimListenerIfAlpha(f.mView, anim);
                                        f.mView.startAnimation(anim);
                                    }
                                    container.addView(f.mView);
                                }
                                if (f.mHidden) f.mView.setVisibility(View.GONE);
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                            } else {
                                f.mInnerView = null;
                            }
                        }

                        f.performActivityCreated(f.mSavedFragmentState);
                        if (f.mView != null) {
                            f.restoreViewState(f.mSavedFragmentState);
                        }
                        f.mSavedFragmentState = null;
                    }
                case Fragment.ACTIVITY_CREATED:
                case Fragment.STOPPED:
                    if (newState > Fragment.STOPPED) {
                        if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                        f.performStart();
                    }
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                        f.performResume();
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                        f.performPause();
                    }
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                        f.performStop();
                    }
                ...
            }
        }
        ...
    }

这里面是简化的代码, 注意看 if (f.mState < newState) {} 中的代码,此时会执行这里面的逻辑,我们发现switch中没有break,也就是说如果条件允许,会从上往下执行。

可能有人会问,为什么会是 f.mState < newState,从刚才添加的逻辑看到现在,似乎这两个值都是默认值,即0,怎么会一个小于另外一个呢?这是因为一开始我们直接分析Fragment的添加流程了,没有分析FragmentActivity中的 onCreate() 方法,我们看一下 onCreate 中有一行代码先执行,mFragments.dispatchCreate();

    FragmentController 中
    public void dispatchCreate() {
        mHost.mFragmentManager.dispatchCreate();
    }

    FragmentManagerImpl 中
    public void dispatchCreate() {
        mStateSaved = false;
        moveToState(Fragment.CREATED, false);
    }
    void moveToState(int newState, boolean always) {
        moveToState(newState, 0, 0, always);
    }
    void moveToState(int newState, int transit, int transitStyle, boolean always) {
        ...
        mCurState = newState;
        if (mActive != null) {
            boolean loadersRunning = false;
            for (int i=0; i<mActive.size(); i++) {
                Fragment f = mActive.get(i);
                if (f != null) {
                    moveToState(f, newState, transit, transitStyle, false);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }
            if (!loadersRunning) {
                startPendingDeferredFragments();
            }
            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                mHost.onSupportInvalidateOptionsMenu();
                mNeedMenuInvalidate = false;
            }
        }
    }

最后这个方法上面出现过,我们发现,把 Fragment.CREATED 这个值传了进来,即 mCurState = Fragment.CREATED; 由于此时 mActive 为null,所以代码到此就停了,这里的一个重要操作就是给 mCurState 赋值了,我们看看 Fragment 中的几个常量值,
    static final int INITIALIZING = 0;     // Not yet created.
    static final int CREATED = 1;          // Created.
    static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
    static final int STOPPED = 3;          // Fully created, not started.
    static final int STARTED = 4;          // Created and started, not resumed.
    static final int RESUMED = 5;          // Created started and resumed.

此时我们在看上面的方法,if (f.mState < newState) 这个判断中,newsState 是从 mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);传进来的,指的是 mManager.mCurState ,即 CREATED ,值为1,而 Fragment 中的 mState 此时为默认值,是0,所以执行到这个 if(f.mState < newState) 中了。switch 中走到 case Fragment.INITIALIZING 中, f.mHost = mHost;  f.onAttach(mHost.getContext());  所以我们会在 Fragment 的 onAttach() 方法中获取 Activity,也可以通过 getActivity() 来获取,我们看一下
    final public FragmentActivity getActivity() {
        return mHost == null ? null : (FragmentActivity) mHost.getActivity();
    }
由于 f.mHost = mHost ,所以这里的 mHost 就是 FragmetnActivity 中的 HostCallbacks,它的基类里有该方法
    Activity getActivity() {
        return mActivity;
    }
这里的 mActivity 就是通过构造方法传进去的,就是 FragmentActivity 本身。所以这两种方法都可以获取到 Fragment 所在的 Activity。

继续往下看, f.performCreate(f.mSavedFragmentState); 这里调用的是 Fragment 中的方法,一开始时 f.mSavedFragmentState 为null,我们看看该方法

    void performCreate(Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = CREATED;
        mCalled = false;
        onCreate(savedInstanceState);
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onCreate()");
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(
                    FragmentActivity.FRAGMENTS_TAG);
            if (p != null) {
                if (mChildFragmentManager == null) {
                    instantiateChildFragmentManager();
                }
                mChildFragmentManager.restoreAllState(p, null);
                mChildFragmentManager.dispatchCreate();
            }
        }
    }
这里面重点看两行代码, mState = CREATED; onCreate(savedInstanceState);  这两行代码 mState = CREATED,是把 Fragment 中的 mState 的值,有0变为了1,onCreate() 方法是我们回调时使用,用来填充代码,写自己的逻辑。 if (f.mFromLayout)  这里走不到, f.mFromLayout 意思是在布局layout中静态填充的写法,咱们这里是通过代码动态生成的,所以
跳过去。 由于这里的switch语句没有使用break,并且上面的Fragment中 mState = CREATED, mState的值变了, 所以到了下一个 case Fragment.CREATED 满足条件,我们看一下,if (newState > Fragment.CREATED) 这个判断中, newState 目前是 CREATED,所以不会执行if的语句,这个case里面也没有break,所以继续找下一个case,但接下来的都不满足条件了。
我们在 Activity 中的 onCreate() 中执行本文开头的添加 Fragment 的方法, commit() 的分析暂时结束,可能有人就有疑惑了,Fragment怎么只有 onCreate() 的生命周期回调,怎么没其他的?它是怎么生成布局的?不用急,接下来继续分析。我们知道 Activity 生命周期,onCreate() 执行后会执行 onStart() ,我们看看 FragmentActivity 中的方法

    protected void onStart() {
        super.onStart();
        mStopped = false;
        mReallyStopped = false;
        mHandler.removeMessages(MSG_REALLY_STOPPED);

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

        mFragments.noteStateNotSaved();
        mFragments.execPendingActions();
        mFragments.doLoaderStart();
        // NOTE: HC onStart goes here.
        mFragments.dispatchStart();
        mFragments.reportLoaderStart();
    }
其他的可以不看,重点看 mFragments.dispatchActivityCreated() 和 mFragments.dispatchStart(); 这两行代码, 上面的加了mCreated 标识判断,说明该调用只会执行一次,我们看看对应的方法
    public void dispatchActivityCreated() {
        mHost.mFragmentManager.dispatchActivityCreated();
    }
    public void dispatchActivityCreated() {
        mStateSaved = false;
        moveToState(Fragment.ACTIVITY_CREATED, false);
    }
    void moveToState(int newState, boolean always) {
        moveToState(newState, 0, 0, always);
    }
    void moveToState(int newState, int transit, int transitStyle, boolean always) {
        ...
        mCurState = newState;
        if (mActive != null) {
            boolean loadersRunning = false;
            for (int i=0; i<mActive.size(); i++) {
                Fragment f = mActive.get(i);
                if (f != null) {
                    moveToState(f, newState, transit, transitStyle, false);
                    if (f.mLoaderManager != null) {
                        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                    }
                }
            }
            ...
        }
    }
我们发现,最终还是调用了 moveToState() 方法,并且 mCurState 的值为 ACTIVITY_CREATED,传入到 moveToState() 方法中的 newState 值也为 ACTIVITY_CREATED,我们看看 if(f.mState < newState) 中,这时候 f.mState 的值为 CREATED, 而 newState 的值为 ACTIVITY_CREATED,所以适配到了 case Fragment.CREATED,此时就满足了if (newState >
Fragment.CREATED) 的判断,我们看看代码, 由于fragmetn是动态添加的,所以会走到 if (!f.mFromLayout) 里面,这里的 f.mContainerId ,是在 transaction.replace(id,fragment) 时 doAddOp()方法中赋值,也就是我们设置的layout中的容器的id; container = (ViewGroup)mContainer.onFindViewById(f.mContainerId); 这里的 mContainer 是通过attachController() 方法赋值的,它对应的是 FragmentActivity 中的 HostCallbacks ,mContainer.onFindViewById() 对应的是 HostCallbacks 中的 onFindViewById() 方法
    public View onFindViewById(int id) {
        return FragmentActivity.this.findViewById(id);
    }
我们看到这就明白了了,原来最终还是通过activity的 findViewById 方法来找到layout中的 ViewGroup,下一步就是调用了 Fragment 的 performCreateView() 方法,同时接收生成的view,
    View performCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        return onCreateView(inflater, container, savedInstanceState);
    }
    @Nullable
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        return null;
    }
我们重写的就是 onCreateView() 方法,继续往下看,如果生成的 f.mView 和 container 都不为 null,会执行container.addView(f.mView); 看到这明白了,原来就是用ViewGroup 来添加 view;接着是 f.onViewCreated(f.mView, f.mSavedFragmentState); f.performActivityCreated(f.mSavedFragmentState); 生命周期回调,注意
    void performActivityCreated(Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = ACTIVITY_CREATED;
        mCalled = false;
        onActivityCreated(savedInstanceState);
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onActivityCreated()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchActivityCreated();
        }
    }
重点关注两行代码, mState = ACTIVITY_CREATED; onActivityCreated(savedInstanceState); 老规矩, Fragment 的mState值在这里再次改变了,我们看看下一个case,发现if (newState > Fragment.STOPPED) 不满足条件,其他case也不满足,就此停止。
我们再看看 mFragments.dispatchStart(); 它对应的逻辑一样,
    public void dispatchStart() {
        mStateSaved = false;
        moveToState(Fragment.STARTED, false);
    }
最终把 moveToState() 中 newState 的值修改为 STARTED,此时switch中会执行到 case Fragment.ACTIVITY_CREATED 中,if (newState > Fragment.STOPPED) 满足条件,执行f.performStart(); 方法,
    void performStart() {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = STARTED;
        mCalled = false;
        onStart();
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onStart()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchStart();
        }
        if (mLoaderManager != null) {
            mLoaderManager.doReportStart();
        }
    }
重点关注 mState = STARTED;  onStart(); 这两行代码, Fragment 中的 mState 值再再次改变。 switch 中 继续往下执行,case Fragment.STARTED 中if语句不满足条件,不会执行。
FragmentActivity 中 onStart() 中分析完毕,下面看看 onResume() 中的代码
    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_RESUME_PENDING:
                    onResumeFragments();
                    mFragments.execPendingActions();
                    break;
            }
        }
    };
    protected void onResume() {
        super.onResume();
        mHandler.sendEmptyMessage(MSG_RESUME_PENDING);
        mResumed = true;
        mFragments.execPendingActions();
    }
    protected void onResumeFragments() {
        mFragments.dispatchResume();
    }
老套路,这一次会调用 moveToState(Fragment.RESUMED, false); 这次把方法中 newState 值修改为 RESUMED,switch中 case Fragment.STARTED 满足条件,if语句也满足,
执行 f.performResume() 方法,
    void performResume() {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = RESUMED;
        mCalled = false;
        onResume();
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onResume()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchResume();
            mChildFragmentManager.execPendingActions();
        }
    }
还是重点两行代码,mState = RESUMED;  onResume();  Fragment 中 mState 值赋值为 RESUMED,同时执行 onResume() 生命周期回调。
Fragment 的创建流程就是这样,如果我们是在view的onClick点击事件中执行了本文开头的代码,此时FragmentActivity已经执行完 onResume() 方法了,那么 FragmentManagerState中的 mCurState 值已经是 RESUMED,这时候通过事务管理器执行 commit() 方法后,switch 语句会 if (f.mState < newState) 中,依次执行 case Fragment.INITIALIZING 、 case Fragment.CREATED 、case Fragment.ACTIVITY_CREATED 、case Fragment.STARTED, 一次性执行到底。 这个是创建过程,那么销毁过程能,同理,也是根据 FragmentActivity 的生命周期控制的,和前面的套路一样,根据 onPause()、 onStop()、 onDestroy() 来调用 Fragment 的方法。Activity 的 onPause() 中会调用 moveToState(Fragment.STARTED,false); 此时传进去的 newState 为 STARTED, 此时 if (f.mState < newState) 就不满足条件了,所以执行 else 操作,此时执行 case Fragment.RESUMED 里操作,if判断满足条件,执行 f.performPause();  其他的地方同理。这里说一下 case Fragment.ACTIVITY_CREATED,这里面会执行 f.performDestroyView();  f.mContainer.removeView(f.mView); 在这里
ViewGroup 移除了里面的 view。 而 Fragment.CREATED 中,f.onDetach() 之后会执行 makeInactive(f) 方法,它里面有一行代码 f.initState();  Fragment 中好些成员变量在此被置空,感兴趣的可以看一下, getActivity() 拿到的 activity 为null的原因就清楚了。

Fragment 一定要保持一个无参构造方法,Android Studio 创建Fragment时会有默认的创建方法,大家可以试试,为什么要这样呢,有什么好处?比如创建 BlankFragment ,

public class BlankFragment extends Fragment {
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private String mParam1;
    private String mParam2;

    public BlankFragment() {
        // Required empty public constructor
    }

    public static BlankFragment newInstance(String param1, String param2) {
        BlankFragment fragment = new BlankFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }
}

我们知道,Activity 在内存吃紧时会造成内存回收,然后会在 onCreate()中通过 bundle 来恢复数据,同样调用牵涉到了 Fragment,

     Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
     mFragments.restoreAllState(p, nc != null ? nc.fragments : null);

    public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
        mHost.mFragmentManager.restoreAllState(state, nonConfigList);
    }

    void restoreAllState(Parcelable state, List<Fragment> nonConfig){}
    
    void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
        ...
        FragmentManagerState fms = (FragmentManagerState)state;
        if (fms.mActive == null) return;
        
        ...
        mActive = new ArrayList<Fragment>(fms.mActive.length);
        if (mAvailIndices != null) {
            mAvailIndices.clear();
        }
        for (int i=0; i<fms.mActive.length; i++) {
            FragmentState fs = fms.mActive[i];
            if (fs != null) {
                // 关注点 
                Fragment f = fs.instantiate(mHost, mParent);
                mActive.add(f);
                fs.mInstance = null;
            } else {
                mActive.add(null);
                if (mAvailIndices == null) {
                    mAvailIndices = new ArrayList<Integer>();
                }
                if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);
                mAvailIndices.add(i);
            }
        }
        ...
    }
关注点 的地方,Fragment f = fs.instantiate(mHost, mParent); 调用的是 FragmentState 中
FragmentState:
    public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
        ...
        mInstance = Fragment.instantiate(context, mClassName, mArguments);
        ...
        return mInstance;
    }
    
Fragment:
public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
        try {
            Class<?> clazz = sClassMap.get(fname);
            if (clazz == null) {
                clazz = context.getClassLoader().loadClass(fname);
                sClassMap.put(fname, clazz);
            }
            Fragment f = (Fragment)clazz.newInstance();
            if (args != null) {
                args.setClassLoader(f.getClass().getClassLoader());
                f.mArguments = args;
            }
            return f;
        } catch (ClassNotFoundException e) {
            ...
        }
    }
    
Fragment f = (Fragment)clazz.newInstance(); 这一行说明了重点,是通过反射调用无参构造创建了Fragment对象,然后通过 f.mArguments = args; 来赋值,所以 AS 推荐的写法是这样。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值