本文共 19522 字,大约阅读时间需要 65 分钟。
Fragment加载到屏幕上的代码非常简单。getFragmentManager().beginTransaction().add(int addId,Fragment addFragment,String tag).commit();但是具体过程我们来看一下: 首先看getFragmentMananger()方法:它定义在Activity中:
- public FragmentManager getFragmentManager() {
- return mFragments;
- }
它只是直接返回了成员变量mFragments。这个变量的类型是FragmentManagerImpl.它是FragmentManager的子类。与FragmentManager和FragmentManagerState处于同一个文件中。而FragmentManager实际上是一个抽象类。
接着看第二个。beginTransaction():
- public FragmentTransaction beginTransaction() {
- return new BackStackRecord(this);
- }
它
将此FragmentManager本身赋给了一个叫做BackStackRecord的类。并将此Manager的实例在内部用一个成员变量保存起来。用于做回退栈栈管理之类的操作。故名思义。这是用于做Fragment回退栈记录处理的类。接着往下看add方法。这个方法是定义在BackStackRecord类中。
- public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
- doAddOp(containerViewId, fragment, tag, OP_ADD);
- return this;
- }
这个方法里面直接将成员变量交给一个叫做doAddOp的方法进行处理。再多传了一个标志位。用于区分add、remove、replace等操作:
- private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- fragment.mFragmentManager = 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 (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;
- }
- Op op = new Op();
- op.cmd = opcmd;
- op.fragment = fragment;
- addOp(op);
- }
这个方法中进行了一些保护性的判断。并
将containerViewId和tag赋给要添加的fragment.并将此fragment
放于一个Op的容器类中。类似我们常用的ViewHolder。它定义在BackStackRecord类中。而在add方法中传过来的参数OP_ADD。将它保存在了op类中的cmd变量中。
- static final class Op {
- Op next;
- Op prev;
- int cmd;
- Fragment fragment;
- int enterAnim;
- int exitAnim;
- int popEnterAnim;
- int popExitAnim;
- ArrayList<Fragment> removed;
- }
- 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++;
- }
这个方法就是把封装了此fragment的op实例保存起来。并将设置的动画也加入其中。 到此add方法算是介绍完了。接下来是commit方法,它也是在BackStackRecord类中定义。
- public int commit() {
- return commitInternal(false);
- }
此处直接调用类中的commitInternal方法。传一个false进入。而我们知道fragment提交时还有一个叫做commitAllowingStateLoss的方法。这个方法内部也是直接调用commitInternal方法。但是传入一个true进入: - int commitInternal(boolean allowStateLoss) {
- if (mCommitted) throw new IllegalStateException("commit already called");
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this);
- mCommitted = true;
- if (mAddToBackStack) {
- mIndex = mManager.allocBackStackIndex(this);
- } else {
- mIndex = -1;
- }
- mManager.enqueueAction(this, allowStateLoss);
- return mIndex;
- }
这个方法中将对此fragment进行入栈操作。使用FragmentManagerImpl对象的enqueueAction方法将将回退栈记录管理类传回去。 下面回到FragmentManagerImpl类中:
- public void enqueueAction(Runnable action, boolean allowStateLoss) {
- if (!allowStateLoss) {
- checkStateLoss();
- }
- synchronized (this) {
- if (mActivity == null) {
- throw new IllegalStateException("Activity has been destroyed");
- }
- if (mPendingActions == null) {
- mPendingActions = new ArrayList<Runnable>();
- }
- mPendingActions.add(action);
- if (mPendingActions.size() == 1) {
- mActivity.mHandler.removeCallbacks(mExecCommit);
- mActivity.mHandler.post(mExecCommit);
- }
- }
- }
allowStateLoss就是当时commitInternal传入的变量。在commit时为false。在commitAllowingStateLoss时为true。所以。在为false时。会调用checkStateLoss来检查状态。接着用了一个同步锁。在里面将BackStackRecord实例装入了mPendingActions的数组中。BackStackRecord是Runnable的子类。再将mExecCommit加入到主线程的handler中进行处理。这也是我们可以连续使用add、replace等在同一条语句的原因。在mExecCommit的Runnable对象中。调用了execPendingActions方法。 - public boolean execPendingActions() {
- if (mExecutingActions) {
- throw new IllegalStateException("Recursive entry to executePendingTransactions");
- }
-
- if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
- throw new IllegalStateException("Must be called from main thread of process");
- }
- 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();
- mActivity.mHandler.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;
- }
这个方法中用了一个while(true)循环对mPendingActions进行操作。所以接着看mPendingActions里面的Runnable对象的run方法。而这个里面保存的是BackStackRecord对象。所以又回到BackStackRecord类中: - public void run() {
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);
- if (mAddToBackStack) {
- if (mIndex < 0) {
- throw new IllegalStateException("addToBackStack() called after commit()");
- }
- }
- bumpBackStackNesting(1);
- Op op = mHead;
- while (op != null) {
- switch (op.cmd) {
- case OP_ADD: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);
- } break;
- case OP_REPLACE: {
- Fragment f = op.fragment;
- if (mManager.mAdded != null) {
- for (int i=0; i<mManager.mAdded.size(); i++) {
- Fragment old = mManager.mAdded.get(i);
- if (FragmentManagerImpl.DEBUG) Log.v(TAG,
- "OP_REPLACE: adding=" + f + " old=" + old);
- if (f == null || old.mContainerId == f.mContainerId) {
- if (old == f) {
- op.fragment = f = null;
- } else {
- if (op.removed == null) {
- op.removed = new ArrayList<Fragment>();
- }
- op.removed.add(old);
- old.mNextAnim = op.exitAnim;
- if (mAddToBackStack) {
- old.mBackStackNesting += 1;
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
- + old + " to " + old.mBackStackNesting);
- }
- mManager.removeFragment(old, mTransition, mTransitionStyle);
- }
- }
- }
- }
- if (f != null) {
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);
- }
- } break;
- case OP_REMOVE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.removeFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_HIDE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.hideFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_SHOW: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.showFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_DETACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.detachFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_ATTACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.attachFragment(f, mTransition, mTransitionStyle);
- } break;
- default: {
- throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
- }
- }
- op = op.next;
- }
- mManager.moveToState(mManager.mCurState, mTransition,
- mTransitionStyle, true);
- if (mAddToBackStack) {
- mManager.addBackStackState(this);
- }
- }
可以看见。在run方法中。它也进行了一个while(true)循环。在里面从Op中一个个的通过next变量取出下一个Op实例。每个Op实例包装一个Fragment实例。方法内部用switch对不同的操作进行区别运行。此处我们看OP_ADD中的代码。它把Fragment实例和它的进行动画取出来。使用FragmentManager管理类addFragment。在addFragment方法中。此将Fragment加入了一个叫做mAdded的成员变量中。类型是ArrayList。范型是Fragment。代表已加入的fragment。然后跳出switch语句。执行FragmentManagerImpl中的moveToState方法。
- void moveToState(int newState, int transit, int transitStyle, boolean always) {
- if (mActivity == null && newState != Fragment.INITIALIZING) {
- throw new IllegalStateException("No activity");
- }
-
- 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 && mActivity != null && mCurState == Fragment.RESUMED) {
- mActivity.invalidateOptionsMenu();
- mNeedMenuInvalidate = false;
- }
- }
- }
一般我们commit的地方在Activity的super.onCreate之后。此处newState为ACTIVITY_CREATED 。状态值总共有如下几个:
- static final int INVALID_STATE = -1;
- static final int INITIALIZING = 0;
- static final int CREATED = 1;
- static final int ACTIVITY_CREATED = 2;
- static final int STOPPED = 3;
- static final int STARTED = 4;
- static final int RESUMED = 5;
在此方法中。程序调用五个参数的moveToState
- void moveToState(Fragment f, int newState, int transit, int transitionStyle,
- boolean keepActive) {
-
- if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
- newState = Fragment.CREATED;
- }
- if (f.mRemoving && newState > f.mState) {
-
- newState = f.mState;
- }
-
-
- if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
- newState = Fragment.STOPPED;
- }
- if (f.mState < newState) {
-
-
-
- if (f.mFromLayout && !f.mInLayout) {
- return;
- }
- if (f.mAnimatingAway != null) {
-
-
-
-
- f.mAnimatingAway = null;
- moveToState(f, f.mStateAfterAnimating, 0, 0, true);
- }
- switch (f.mState) {
- case Fragment.INITIALIZING:
- if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
- if (f.mSavedFragmentState != null) {
- f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
- FragmentManagerImpl.VIEW_STATE_TAG);
- f.mTarget = getFragment(f.mSavedFragmentState,
- FragmentManagerImpl.TARGET_STATE_TAG);
- if (f.mTarget != null) {
- f.mTargetRequestCode = f.mSavedFragmentState.getInt(
- FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
- }
- f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
- FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
- if (!f.mUserVisibleHint) {
- f.mDeferStart = true;
- if (newState > Fragment.STOPPED) {
- newState = Fragment.STOPPED;
- }
- }
- }
- f.mActivity = mActivity;
- f.mParentFragment = mParent;
- f.mFragmentManager = mParent != null
- ? mParent.mChildFragmentManager : mActivity.mFragments;
- f.mCalled = false;
- f.onAttach(mActivity);
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onAttach()");
- }
- if (f.mParentFragment == null) {
- mActivity.onAttachFragment(f);
- }
- if (!f.mRetaining) {
- f.performCreate(f.mSavedFragmentState);
- }
- f.mRetaining = false;
- if (f.mFromLayout) {
-
-
-
- f.mView = f.performCreateView(f.getLayoutInflater(
- f.mSavedFragmentState), null, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mInnerView = f.mView;
- f.mView = NoSaveStateFrameLayout.wrap(f.mView);
- if (f.mHidden) f.mView.setVisibility(View.GONE);
- f.onViewCreated(f.mView, f.mSavedFragmentState);
- } else {
- f.mInnerView = null;
- }
- }
- 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.findViewById(f.mContainerId);
- if (container == null && !f.mRestored) {
- throwException(new IllegalArgumentException(
- "No view found for id 0x"
- + Integer.toHexString(f.mContainerId) + " ("
- + f.getResources().getResourceName(f.mContainerId)
- + ") for fragment " + f));
- }
- }
- f.mContainer = container;
- f.mView = f.performCreateView(f.getLayoutInflater(
- f.mSavedFragmentState), container, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mInnerView = f.mView;
- f.mView = NoSaveStateFrameLayout.wrap(f.mView);
- if (container != null) {
- Animation anim = loadAnimation(f, transit, true,
- transitionStyle);
- if (anim != null) {
- 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.mResumed = true;
- 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();
- f.mResumed = false;
- }
- case Fragment.STARTED:
- if (newState < Fragment.STARTED) {
- if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
- f.performStop();
- }
- case Fragment.STOPPED:
- if (newState < Fragment.STOPPED) {
- if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
- f.performReallyStop();
- }
- case Fragment.ACTIVITY_CREATED:
- if (newState < Fragment.ACTIVITY_CREATED) {
- if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
- if (f.mView != null) {
-
-
- if (!mActivity.isFinishing() && f.mSavedViewState == null) {
- saveFragmentViewState(f);
- }
- }
- f.performDestroyView();
- if (f.mView != null && f.mContainer != null) {
- Animation anim = null;
- if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
- anim = loadAnimation(f, transit, false,
- transitionStyle);
- }
- if (anim != null) {
- final Fragment fragment = f;
- f.mAnimatingAway = f.mView;
- f.mStateAfterAnimating = newState;
- anim.setAnimationListener(new AnimationListener() {
- @Override
- public void onAnimationEnd(Animation animation) {
- if (fragment.mAnimatingAway != null) {
- fragment.mAnimatingAway = null;
- moveToState(fragment, fragment.mStateAfterAnimating,
- 0, 0, false);
- }
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- @Override
- public void onAnimationStart(Animation animation) {
- }
- });
- f.mView.startAnimation(anim);
- }
- f.mContainer.removeView(f.mView);
- }
- f.mContainer = null;
- f.mView = null;
- f.mInnerView = null;
- }
- case Fragment.CREATED:
- if (newState < Fragment.CREATED) {
- if (mDestroyed) {
- if (f.mAnimatingAway != null) {
-
-
-
-
-
-
- View v = f.mAnimatingAway;
- f.mAnimatingAway = null;
- v.clearAnimation();
- }
- }
- if (f.mAnimatingAway != null) {
-
-
-
-
- f.mStateAfterAnimating = newState;
- newState = Fragment.CREATED;
- } else {
- if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
- if (!f.mRetaining) {
- f.performDestroy();
- }
- f.mCalled = false;
- f.onDetach();
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onDetach()");
- }
- if (!keepActive) {
- if (!f.mRetaining) {
- makeInactive(f);
- } else {
- f.mActivity = null;
- f.mFragmentManager = null;
- }
- }
- }
- }
- }
- }
-
- f.mState = newState;
- }
重要的终于到了啊!这个方法中会先依次走INITIALIZING,CREATED,ACTIVITY_CREATED代码段。之后会根据Activity的生命周期走自己相应的生命周期函数。在此对应的是STARTED,RESUMED; 由于是初次加载Fragment。所以f.mState是小于newState的。所以走的都是f.mState<newState中的switch语句。
- case Fragment.INITIALIZING:
- if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
- if (f.mSavedFragmentState != null) {
- f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
- FragmentManagerImpl.VIEW_STATE_TAG);
- f.mTarget = getFragment(f.mSavedFragmentState,
- FragmentManagerImpl.TARGET_STATE_TAG);
- if (f.mTarget != null) {
- f.mTargetRequestCode = f.mSavedFragmentState.getInt(
- FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
- }
- f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
- FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
- if (!f.mUserVisibleHint) {
- f.mDeferStart = true;
- if (newState > Fragment.STOPPED) {
- newState = Fragment.STOPPED;
- }
- }
- }
- f.mActivity = mActivity;
- f.mFragmentManager = mActivity.mFragments;
- f.mCalled = false;
- f.onAttach(mActivity);
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onAttach()");
- }
- mActivity.onAttachFragment(f);
-
- if (!f.mRetaining) {
- f.mCalled = false;
- f.onCreate(f.mSavedFragmentState);
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onCreate()");
- }
- }
- f.mRetaining = false;
- if (f.mFromLayout) {
-
-
-
- f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
- null, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mView.setSaveFromParentEnabled(false);
- if (f.mHidden) f.mView.setVisibility(View.GONE);
- f.onViewCreated(f.mView, f.mSavedFragmentState);
- }
- }
- case Fragment.CREATED:
在f.mSavedFragmentState != null这个条件判断语句块中。是屏幕切换时或因其他原因引起的fragment被销毁后重新恢复时走的语句块。在此不用理会。接着后面,熟悉的代码出现了,f.onAttach(mActivity),第一个生命周期方法。这里面就可以拿到与此fragment相绑定的Activity的实例。接着往下看。f.onCreate(f.mSavedFragmentState)。走onCreate回调了。 而f.mFromLayout在此时为false。故不用理会。
- 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)mActivity.findViewById(f.mContainerId);
- if (container == null && !f.mRestored) {
- throw new IllegalArgumentException("No view found for id 0x"
- + Integer.toHexString(f.mContainerId)
- + " for fragment " + f);
- }
- }
- f.mContainer = container;
- f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
- container, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mView.setSaveFromParentEnabled(false);
- if (container != null) {
- Animator anim = loadAnimator(f, transit, true,
- transitionStyle);
- if (anim != null) {
- anim.setTarget(f.mView);
- anim.start();
- }
- container.addView(f.mView);
- }
- if (f.mHidden) f.mView.setVisibility(View.GONE);
- f.onViewCreated(f.mView, f.mSavedFragmentState);
- }
- }
-
- f.mCalled = false;
- f.onActivityCreated(f.mSavedFragmentState);
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onActivityCreated()");
- }
- if (f.mView != null) {
- f.restoreViewState();
- }
- f.mSavedFragmentState = null;
- }
- case Fragment.ACTIVITY_CREATED:
重点来了!newState此时的值为ACTIVITY_CREATED。故可以进入语句块,在内部先通过Activity的findViewById方法通过add的containerid来得到要添加fragment的ViewGroup。再将其赋给fragment的mContainer成员变量中。接下来通过fragment的onCreateView回调。将创建的view放入fragment的view成员变量中。接下来就是加载fragment的动画以及将创建的view通过addView方法放于容器中了。至此。成功将fragment嵌入到了界面上
转载地址:http://eggwn.baihongyu.com/