1. 程式人生 > >android.support.v4.app.Fragment原始碼解析

android.support.v4.app.Fragment原始碼解析

Fragment最基礎功能使用

FragmentManager fm=getFragmentManager();  
FragmentTransaction transaction=fm.beginTransaction();  
mFirstFragment=new FirstFragment();  
transaction.add(R.id.fragment,mFirstFragment);  
transaction.commit();  

中逐一跟進原始碼
(1)從Activity獲取getFragmentManager()

    public FragmentManager getSupportFragmentManager
() { return this.mFragments; } final FragmentManagerImpl mFragments = new FragmentManagerImpl();

FragmentManagerImpl是FragmentManager抽象類的具體實現,FragmentManager定義了獲取事務beginTransaction(),已進棧的Fragment getFragments()。。。

public abstract class FragmentManager {
    public static final int POP_BACK_STACK_INCLUSIVE = 1
; public abstract FragmentTransaction beginTransaction(); @Deprecated public FragmentTransaction openTransaction() { return this.beginTransaction(); } public abstract boolean executePendingTransactions(); public abstract Fragment findFragmentById(int arg0); public
abstract Fragment findFragmentByTag(String arg0); public abstract void popBackStack(); public abstract boolean popBackStackImmediate(); public abstract void popBackStack(String arg0, int arg1); public abstract boolean popBackStackImmediate(String arg0, int arg1); public abstract void popBackStack(int arg0, int arg1); public abstract boolean popBackStackImmediate(int arg0, int arg1); public abstract int getBackStackEntryCount(); public abstract FragmentManager.BackStackEntry getBackStackEntryAt(int arg0); public abstract void addOnBackStackChangedListener(FragmentManager.OnBackStackChangedListener arg0); public abstract void removeOnBackStackChangedListener(FragmentManager.OnBackStackChangedListener arg0); public abstract void putFragment(Bundle arg0, String arg1, Fragment arg2); public abstract Fragment getFragment(Bundle arg0, String arg1); public abstract List<Fragment> getFragments(); public abstract SavedState saveFragmentInstanceState(Fragment arg0); public abstract boolean isDestroyed(); public abstract void dump(String arg0, FileDescriptor arg1, PrintWriter arg2, String[] arg3); public static void enableDebugLogging(boolean enabled) { FragmentManagerImpl.DEBUG = enabled; } public interface BackStackEntry { int getId(); String getName(); int getBreadCrumbTitleRes(); int getBreadCrumbShortTitleRes(); CharSequence getBreadCrumbTitle(); CharSequence getBreadCrumbShortTitle(); } public interface OnBackStackChangedListener { void onBackStackChanged(); } }

(2)獲取事務FragmentTransaction
FragmentManagerImpl中例項化FragmentTransaction

    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

(3)BackStackRecord

final class BackStackRecord extends FragmentTransaction implements BackStackEntry, Runnable

( 4 ) 新增事務add
BackStackRecord內部維護了一個儲存Fragment的雙向連結串列,往連結串列尾部新增新Fragment

    void addOp(BackStackRecord.Op op) {
        if (this.mHead == null) {
            this.mHead = this.mTail = op;
        } else {
            op.prev = this.mTail;
            this.mTail.next = op;
            this.mTail = op;
        }

        op.enterAnim = this.mEnterAnim;
        op.exitAnim = this.mExitAnim;
        op.popEnterAnim = this.mPopEnterAnim;
        op.popExitAnim = this.mPopExitAnim;
        ++this.mNumOp;
    }

( 5 )提交事務commit
不管是commit還是commitAllowingStateLoss,內部都執行了commitInternal(boolean allowStateLoss) ,最後通過FragmentManagerImpl
this.mManager.enqueueAction(this, allowStateLoss);

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

        synchronized (this) {
            if (!this.mDestroyed && this.mActivity != null) {
                if (this.mPendingActions == null) {
                    this.mPendingActions = new ArrayList();
                }

                this.mPendingActions.add(action);
                if (this.mPendingActions.size() == 1) {
                    this.mActivity.mHandler.removeCallbacks(this.mExecCommit);
                    this.mActivity.mHandler.post(this.mExecCommit);
                }

            } else {
                throw new IllegalStateException("Activity has been destroyed");
            }
        }
    }

mPendingActions是裝載Runnable的集合,enqueueAction就是把Runnable (BackStackRecord)加入到了集合中,
然後執行了mExecCommit(Runnble)

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

execPendingActions是將mPendingActions的Runnable拷貝到mTmpActions,最後執行mTmpActions[i].run()(即BackStackRecord.run())執行了transaction.add(通過BackStackRecord.Op op的標誌識別操作)操作

public boolean execPendingActions() {
        if (this.mExecutingActions) {
            throw new IllegalStateException("Recursive entry to executePendingTransactions");
        } else if (Looper.myLooper() != this.mActivity.mHandler.getLooper()) {
            throw new IllegalStateException("Must be called from main thread of process");
        } else {
            boolean didSomething = false;

            int i;
            while (true) {
                int loadersRunning;
                synchronized (this) {
                    if (this.mPendingActions == null || this.mPendingActions.size() == 0) {
                        break;
                    }

                    loadersRunning = this.mPendingActions.size();
                    if (this.mTmpActions == null || this.mTmpActions.length < loadersRunning) {
                        this.mTmpActions = new Runnable[loadersRunning];
                    }

                    this.mPendingActions.toArray(this.mTmpActions);
                    this.mPendingActions.clear();
                    this.mActivity.mHandler.removeCallbacks(this.mExecCommit);
                }

                this.mExecutingActions = true;

                for (i = 0; i < loadersRunning; ++i) {
                    this.mTmpActions[i].run();
                    this.mTmpActions[i] = null;
                }

                this.mExecutingActions = false;
                didSomething = true;
            }

            if (this.mHavePendingDeferredStart) {
                boolean arg5 = false;

                for (i = 0; i < this.mActive.size(); ++i) {
                    Fragment f = (Fragment) this.mActive.get(i);
                    if (f != null && f.mLoaderManager != null) {
                        arg5 |= f.mLoaderManager.hasRunningLoaders();
                    }
                }

                if (!arg5) {
                    this.mHavePendingDeferredStart = false;
                    this.startPendingDeferredFragments();
                }
            }

            return didSomething;
        }
    }

根據標識執行事務

public void run() {
        if (FragmentManagerImpl.DEBUG) {
            Log.v("FragmentManager", "Run: " + this);
        }

        if (this.mAddToBackStack && this.mIndex < 0) {
            throw new IllegalStateException("addToBackStack() called after commit()");
        } else {
            this.bumpBackStackNesting(1);

            for (BackStackRecord.Op op = this.mHead; op != null; op = op.next) {
                Fragment f;
                switch (op.cmd) {
                case 1:
                    f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    this.mManager.addFragment(f, false);
                    break;
                case 2:
                    f = op.fragment;
                    if (this.mManager.mAdded != null) {
                        for (int i = 0; i < this.mManager.mAdded.size(); ++i) {
                            Fragment old = (Fragment) this.mManager.mAdded.get(i);
                            if (FragmentManagerImpl.DEBUG) {
                                Log.v("FragmentManager", "OP_REPLACE: adding=" + f + " old=" + old);
                            }

                            if (f == null || old.mContainerId == f.mContainerId) {
                                if (old == f) {
                                    f = null;
                                    op.fragment = null;
                                } else {
                                    if (op.removed == null) {
                                        op.removed = new ArrayList();
                                    }

                                    op.removed.add(old);
                                    old.mNextAnim = op.exitAnim;
                                    if (this.mAddToBackStack) {
                                        ++old.mBackStackNesting;
                                        if (FragmentManagerImpl.DEBUG) {
                                            Log.v("FragmentManager",
                                                    "Bump nesting of " + old + " to " + old.mBackStackNesting);
                                        }
                                    }

                                    this.mManager.removeFragment(old, this.mTransition, this.mTransitionStyle);
                                }
                            }
                        }
                    }

                    if (f != null) {
                        f.mNextAnim = op.enterAnim;
                        this.mManager.addFragment(f, false);
                    }
                    break;
                case 3:
                    f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    this.mManager.removeFragment(f, this.mTransition, this.mTransitionStyle);
                    break;
                case 4:
                    f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    this.mManager.hideFragment(f, this.mTransition, this.mTransitionStyle);
                    break;
                case 5:
                    f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    this.mManager.showFragment(f, this.mTransition, this.mTransitionStyle);
                    break;
                case 6:
                    f = op.fragment;
                    f.mNextAnim = op.exitAnim;
                    this.mManager.detachFragment(f, this.mTransition, this.mTransitionStyle);
                    break;
                case 7:
                    f = op.fragment;
                    f.mNextAnim = op.enterAnim;
                    this.mManager.attachFragment(f, this.mTransition, this.mTransitionStyle);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
                }
            }

            this.mManager.moveToState(this.mManager.mCurState, this.mTransition, this.mTransitionStyle, true);
            if (this.mAddToBackStack) {
                this.mManager.addBackStackState(this);
            }

        }
    }

run方法執行完最後執行,

        this.mManager.moveToState(this.mManager.mCurState, this.mTransition, this.mTransitionStyle, true);
            if (this.mAddToBackStack) {
                this.mManager.addBackStackState(this);
            }

moveToState是把每次執行完的狀態儲存到Fragment中,這個方法最終會將FragmentManager的狀態賦值給fragment(過程:通過Activity生命週期的回撥和Fragment的狀態執行Fragment獨有的生命週期方法)
addBackStackState是加入回退棧