Android Fragment 和 FragmentManager 的代码分析
这两天在研究插件化编程,在使用Fragment碰到了一些问题,于是查看源码,顺便分析了一下Fragment和FragmentManager以及其他几个API的原代码,看看他们是怎么工作的。
我们知道Fragment有个onCreateView()方法,这个方法在Fragment创建View的时候被调用,并且返回一个View对象。那么onCreateView在什么时候被调用呢,咱们在Fragment这个类里找到了一个方法,performCreateView()方法。
Fragment.java publicViewonCreateView(LayoutInflaterinflater,@NullableViewGroupcontainer, @NullableBundlesavedInstanceState){ returnnull; }
performCreateView这个方法在什么时候会被调用呢,在Fragment里找不到调用它的代码。咱们可以猜测一下,大概会在FragmentManager里。
ViewperformCreateView(LayoutInflaterinflater,ViewGroupcontainer, BundlesavedInstanceState){ if(mChildFragmentManager!=null){ mChildFragmentManager.noteStateNotSaved(); } returnonCreateView(inflater,container,savedInstanceState); }
在FragmentManager里,咱们找到了调用Fragment.performCreateView的代码,在moveToState()方法里,这个方法有点大,我只粘贴了部分代码。可以看到,它会在Fragment初始化或者创建的时候被调用。并且我们知道,创建的View被赋值给Fragment的mView成员变量了。
FragmentManager.java voidmoveToState(Fragmentf,intnewState,inttransit,inttransitionStyle,booleankeepActive){ switch(f.mState){ caseFragment.INITIALIZING: if(f.mFromLayout){ f.mView=f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState),null,f.mSavedFragmentState); } break; caseFragment.CREATED: if(!f.mFromLayout){ f.mView=f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState),container,f.mSavedFragmentState); } break; } }
接下来,咱们要看什么时候会调用moveToState()这个方法。找了一下,发现很N多的地方调用了这个方法。这样给咱们逆推找代码造成了一定的难度。于是咱们换个思路,正推来分析。怎么正推了,看咱们怎么使用Fragment和FragmentManager来分析。
一般咱们都是getFragmentManager()或者getSupportFragmentManager()的方法来获取FragmentManager.以FragmentActivity为例,一般情况下,咱们在这个类的子类里调用这两个方法之一。
咱们在FragmentActivity里找到了相应的代码。FragmentManager是一个抽象类,FragmentManagerImpl是FragmentManager的子类,在FragmentManager同一个java文件内,是一个内部类。它是FragmentManager的实现。
FragmentActivity.java //FragmentManagerImplissubclassofFragmentManager finalFragmentManagerImplmFragments=newFragmentManagerImpl(); publicFragmentManagergetSupportFragmentManager(){ returnmFragments; }
获取到FragmentManager后,咱们一般就会调用beginTransaction()方法,返回一个FragmentTransaction。咱们看代码去。
FragmentManager.java publicabstractFragmentTransactionbeginTransaction(); FragmentManagerImplextendsFragmentManager @Override publicFragmentTransactionbeginTransaction(){ returnnewBackStackRecord(this); } /** *Staticlibrarysupportversionoftheframework's{@linkandroid.app.FragmentTransaction}. *UsedtowriteappsthatrunonplatformspriortoAndroid3.0.Whenrunning *onAndroid3.0orabove,thisimplementationisstillused;itdoesnottry *toswitchtotheframework'simplementation.SeetheframeworkSDK *documentationforaclassoverview. */ publicabstractclassFragmentTransaction
我们发现FragmentManager是一个抽象方法,实现在FragmentManagerImpl。FragmentManagerImpl.beginTransaction()返回的是一个BackStackRecord,而FragmentTransaction是一个抽象类。那么BackStackRecord是个什么鬼。
我们找到了BackStackRecord这个类。我们注意到,它继承于FragmentTransaction,并且实现了Runable接口。它的方法有很多,咱们就分析一个咱们比较常用的,比如add()方法。
BackStackRecord.java finalclassBackStackRecordextendsFragmentTransactionimplementsFragmentManager.BackStackEntry,Runnable finalFragmentManagerImplmManager; publicBackStackRecord(FragmentManagerImplmanager){ mManager=manager; }
add()方法其实没干啥,咱们一路追下去看。
publicFragmentTransactionadd(Fragmentfragment,Stringtag){ doAddOp(0,fragment,tag,OP_ADD); returnthis; } privatevoiddoAddOp(intcontainerViewId,Fragmentfragment,Stringtag,intopcmd){ fragment.mFragmentManager=mManager; if(tag!=null){ if(fragment.mTag!=null&&!tag.equals(fragment.mTag)){ thrownewIllegalStateException("Can'tchangetagoffragment" +fragment+":was"+fragment.mTag +"now"+tag); } fragment.mTag=tag; } if(containerViewId!=0){ if(fragment.mFragmentId!=0&&fragment.mFragmentId!=containerViewId){ thrownewIllegalStateException("Can'tchangecontainerIDoffragment" +fragment+":was"+fragment.mFragmentId +"now"+containerViewId); } fragment.mContainerId=fragment.mFragmentId=containerViewId; } Opop=newOp(); op.cmd=opcmd; op.fragment=fragment; addOp(op); } voidaddOp(Opop){ 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++; }
一直追到addOp()就断了,好像啥事也没干。不过它大概是在一个add操作添加到一个链表上了。那咱们怎么办呢?一般咱们add完后会commit一下,咱们看看commit都干了啥。
publicintcommit(){ returncommitInternal(false); } intcommitInternal(booleanallowStateLoss){ if(mCommitted)thrownewIllegalStateException("commitalreadycalled"); mCommitted=true; if(mAddToBackStack){ mIndex=mManager.allocBackStackIndex(this); }else{ mIndex=-1; } mManager.enqueueAction(this,allowStateLoss); returnmIndex; }
commit好像也没干啥特殊的事情,不过可以看到这么一行代码mManager.enqueueAction(this,allowStateLoss);看enqueueAction这个方法名,应该会做点事情的。
同样,咱们在FragmentManagerImpl里找到了这个方法。
publicvoidenqueueAction(Runnableaction,booleanallowStateLoss){ if(!allowStateLoss){ checkStateLoss(); } synchronized(this){ if(mDestroyed||mActivity==null){ thrownewIllegalStateException("Activityhasbeendestroyed"); } if(mPendingActions==null){ mPendingActions=newArrayList<Runnable>(); } mPendingActions.add(action); if(mPendingActions.size()==1){ mActivity.mHandler.removeCallbacks(mExecCommit); mActivity.mHandler.post(mExecCommit); } } }
这个方法把咱们的BackStackRecord--其实是FragmentTransaction,也是Runnable--添加到一个mPendingActions的ArrayList里了。然后调用mActivity.mHandler.post(mExecCommit);mExecCommit又是什么鬼?
RunnablemExecCommit=newRunnable(){ @Override publicvoidrun(){ execPendingActions(); } }; mActivity.mHandler.post(mExecCommit);说明它在主线程里执行了mExecCommit的run方法。别问我咋知道的。 execPendingActions()方法稍微比较大,我把注释写在代码里。 publicbooleanexecPendingActions(){ if(mExecutingActions){ thrownewIllegalStateException("RecursiveentrytoexecutePendingTransactions"); } //如果不是在主线程,抛出一个异常。 if(Looper.myLooper()!=mActivity.mHandler.getLooper()){ thrownewIllegalStateException("Mustbecalledfrommainthreadofprocess"); } booleandidSomething=false; //这里有一个whiletrue循环。 while(true){ intnumActions; //这里在一个同步语句块里,把上次mPendingActions里的元素转移到mTmpActions数组里。并且执行run方法。执行谁的run方法呢?!就是BackStackRecord,也就是FragmentTransaction。我在最后面贴了BackStackRecord的run方法。 synchronized(this){ if(mPendingActions==null||mPendingActions.size()==0){ break; } numActions=mPendingActions.size(); if(mTmpActions==null||mTmpActions.length<numActions){ mTmpActions=newRunnable[numActions]; } mPendingActions.toArray(mTmpActions); mPendingActions.clear(); mActivity.mHandler.removeCallbacks(mExecCommit); } mExecutingActions=true; for(inti=0;i<numActions;i++){ mTmpActions[i].run(); mTmpActions[i]=null; } mExecutingActions=false; didSomething=true; } //这里有好几行代码,不知道干啥的,反正就是做了一些判断,最后可能会调用startPendingDeferredFragments()方法。 if(mHavePendingDeferredStart){ booleanloadersRunning=false; for(inti=0;i<mActive.size();i++){ Fragmentf=mActive.get(i); if(f!=null&&f.mLoaderManager!=null){ loadersRunning|=f.mLoaderManager.hasRunningLoaders(); } } if(!loadersRunning){ mHavePendingDeferredStart=false; startPendingDeferredFragments(); } } returndidSomething; }
startPendingDeferredFragments方法又是一坨不知道啥意思的代码。最后可能调用了performPendingDeferredStart()
voidstartPendingDeferredFragments(){ if(mActive==null)return; for(inti=0;i<mActive.size();i++){ Fragmentf=mActive.get(i); if(f!=null){ performPendingDeferredStart(f); } } }
在这个方法里,咱们看到了很熟悉的moveToState()方法。接着就是上面的分析,Fragment的onCreateView会被调用。
publicvoidperformPendingDeferredStart(Fragmentf){ if(f.mDeferStart){ if(mExecutingActions){ //Waituntilwe'redoneexecutingourpendingtransactions mHavePendingDeferredStart=true; return; } f.mDeferStart=false; moveToState(f,mCurState,0,0,false); } }
咱们在回来看BackStackRecord的run方法。这坨代码有点大,我还是写注释在代码里。
publicvoidrun(){ if(FragmentManagerImpl.DEBUG)Log.v(TAG,"Run:"+this); if(mAddToBackStack){ if(mIndex<0){ thrownewIllegalStateException("addToBackStack()calledaftercommit()"); } } bumpBackStackNesting(1); TransitionStatestate=null; SparseArray<Fragment>firstOutFragments=null; SparseArray<Fragment>lastInFragments=null; if(SUPPORTS_TRANSITIONS){ firstOutFragments=newSparseArray<Fragment>(); lastInFragments=newSparseArray<Fragment>(); calculateFragments(firstOutFragments,lastInFragments); state=beginTransition(firstOutFragments,lastInFragments,false); } inttransitionStyle=state!=null?0:mTransitionStyle; inttransition=state!=null?0:mTransition; //注意这里要开始while循环了,要遍历刚才咱们说的链表了。 Opop=mHead; while(op!=null){ intenterAnim=state!=null?0:op.enterAnim; intexitAnim=state!=null?0:op.exitAnim; switch(op.cmd){ //OP_ADD很简单,mManager.addFragment(f,false);其他的几个也类似,调用mManager相应的方法。 caseOP_ADD:{ Fragmentf=op.fragment; f.mNextAnim=enterAnim; mManager.addFragment(f,false); }break; caseOP_REPLACE:{ Fragmentf=op.fragment; if(mManager.mAdded!=null){ for(inti=0;i<mManager.mAdded.size();i++){ Fragmentold=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=newArrayList<Fragment>(); } op.removed.add(old); old.mNextAnim=exitAnim; if(mAddToBackStack){ old.mBackStackNesting+=1; if(FragmentManagerImpl.DEBUG)Log.v(TAG,"Bumpnestingof" +old+"to"+old.mBackStackNesting); } mManager.removeFragment(old,transition,transitionStyle); } } } } if(f!=null){ f.mNextAnim=enterAnim; mManager.addFragment(f,false); } }break; caseOP_REMOVE:{ Fragmentf=op.fragment; f.mNextAnim=exitAnim; mManager.removeFragment(f,transition,transitionStyle); }break; caseOP_HIDE:{ Fragmentf=op.fragment; f.mNextAnim=exitAnim; mManager.hideFragment(f,transition,transitionStyle); }break; caseOP_SHOW:{ Fragmentf=op.fragment; f.mNextAnim=enterAnim; mManager.showFragment(f,transition,transitionStyle); }break; caseOP_DETACH:{ Fragmentf=op.fragment; f.mNextAnim=exitAnim; mManager.detachFragment(f,transition,transitionStyle); }break; caseOP_ATTACH:{ Fragmentf=op.fragment; f.mNextAnim=enterAnim; mManager.attachFragment(f,transition,transitionStyle); }break; default:{ thrownewIllegalArgumentException("Unknowncmd:"+op.cmd); } } op=op.next; } //最后还调用了moveToState()这个方法。跟刚才的区别,看最后一个参数,一个true,一个false。 //而且注意,这行代码在while循环之后。 mManager.moveToState(mManager.mCurState,transition,transitionStyle,true); if(mAddToBackStack){ mManager.addBackStackState(this); } }
以上所述是小编给大家介绍的AndroidFragment和FragmentManager的代码分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!