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的代码分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!