先从fragment基本用法出发:
getSupportFragmentManager().beginTransaction()
.add(R.id.basic, new PageFragment()).commit();其中点进去getSupportFragmentManager()可以看到跳转到FragmentActivity:
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}先看下mFragments是啥:
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}往下看.
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}看样子是调用了FragmentHostCallback的getFragmentManagerImpl(),往下看HostCallbaks的代码:
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
@Override
public LayoutInflater onGetLayoutInflater() {
return FragmentActivity.this.getLayoutInflater().cloneInContext(FragmentActivity.this);
}
//代码省略...
@Override
public FragmentActivity onGetHost() {
return FragmentActivity.this;
}
@Override
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode);
}
//代码省略...
@Override
public void onStartActivityFromFragment(
Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) {
FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode, options);
}
@Override
public void onRequestPermissionsFromFragment(@NonNull Fragment fragment,
@NonNull String[] permissions, int requestCode) {
FragmentActivity.this.requestPermissionsFromFragment(fragment, permissions,
requestCode);
}
@Override
public void onAttachFragment(Fragment fragment) {
FragmentActivity.this.onAttachFragment(fragment);
}
//代码省略...
@Nullable
@Override
public View onFindViewById(int id) {
return FragmentActivity.this.findViewById(id);
}
//代码省略...
}先有个印象,这里还有startActivity这样的方法,其实Fragment中启动的方法都是调用这里的,而且HostCallbacks是FragmentActivity的内部类,所以构造方法直接持有了Activity引用.
这里没找到getSupportFragmentManager()方法,再看看它的父类:
public abstract class FragmentHostCallback<E> extends FragmentContainer {
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
//省略大部分代码
public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
this(context instanceof Activity ? (Activity) context : null, context, handler,
windowAnimations);
}
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
FragmentHostCallback(Activity activity, Context context, Handler handler,
int windowAnimations) {
mActivity = activity;
mContext = context;
mHandler = handler;
mWindowAnimations = windowAnimations;
}
/**
* Return a {@link LayoutInflater}.
* See {@link Activity#getLayoutInflater()}.
*/
public LayoutInflater onGetLayoutInflater() {
return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
Activity getActivity() {
return mActivity;
}
Context getContext() {
return mContext;
}
Handler getHandler() {
return mHandler;
}
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
}可以看到子类没有重写getSupportFragmentManager()方法,所以获得的对象就是FragmentMangerImpl了.再继续往下看beginTransaction()方法:
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}又可以看到beginTransaction()返回的对象是BacStateRecord,继续往下看
@Override
public FragmentTransaction add(Fragment fragment, String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
@Override
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
@Override
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
+ " instance state.");
}
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 (containerViewId == View.NO_ID) {
throw new IllegalArgumentException("Can't add fragment "
+ fragment + " with tag " + tag + " to container view with no id");
}
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);
}
@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
return replace(containerViewId, fragment, null);
}
@Override
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;
}
@Override
public FragmentTransaction remove(Fragment fragment) {
Op op = new Op();
op.cmd = OP_REMOVE;
op.fragment = fragment;
addOp(op);
return this;
}
@Override
public FragmentTransaction hide(Fragment fragment) {
Op op = new Op();
op.cmd = OP_HIDE;
op.fragment = fragment;
addOp(op);
return this;
}
@Override
public FragmentTransaction show(Fragment fragment) {
Op op = new Op();
op.cmd = OP_SHOW;
op.fragment = fragment;
addOp(op);
return this;
}
void addOp(Op op) {
mOps.add(op);
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
}所有add方法和replace方法都调用到doAppOp方法,然后最终都回调到addOp方法。
先看下doAppOp方法,首先先检测fragment是不是匿名类或者不是公共类或者是成员变量且是静态的,就抛出异常.
接下来给fragment赋值,首先就是赋值mFragmentManager为FragmentMangerImpl,如果用户设置tag,则再设置fragment的tag,如果之前设置过就报错,mContainerId同理,接下来看Op这个类:
static final class Op {
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
}就几个成员变量,cmd都是设为1,然后放入fragment,然后放入设置的动画.show和hide也调用该方法,然后看最后一步commit:
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
@Override
public void commitNow() {
disallowAddToBackStack();
mManager.execSingleAction(this, false);
}
@Override
public void commitNowAllowingStateLoss() {
disallowAddToBackStack();
mManager.execSingleAction(this, true);
}
@Override
public FragmentTransaction setAllowOptimization(boolean allowOptimization) {
mAllowOptimization = allowOptimization;
return this;
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", null, pw, null);
pw.close();
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex; commit操作都调用了commitInternal方法,这里有个mCommit控制,如果同一个BackStackRecord对象第二次再commit,是会报错的,DEBUG模式下打印log,
mAddToBackStack赋值在以下代码:
@Override
public FragmentTransaction disallowAddToBackStack() {
if (mAddToBackStack) {
throw new IllegalStateException(
"This transaction is already being added to the back stack");
}
mAllowAddToBackStack = false;
return this;
}如果mAddToBackStack为true,则加入到FragmentManger的一个集合中,并返回在当前集合中的位置,代码如下:
public int allocBackStackIndex(BackStackRecord bse) {
synchronized (this) {
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.add(bse);
return index;
} else {
int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.set(index, bse);
return index;
}
}
}public void enqueueAction(OpGenerator 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<>();
}
mPendingActions.add(action);
scheduleCommit();
}
}private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}判断mStateSaved是否保存,如果保存了则不允许再次
提交,然后报错,也就是说commit()必须在onSaveInstanceState()方法之前调用,不然就是抛异常了.
继续往下看,这里用synchronized锁,如果被销毁了或者mHost为空,则报异常说activity已经销毁了,这个mHost是持有activity的引用的.队列为空则创建队列,然后加入当前的action,当前action实现的方法如下:
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Run: " + this);
}
records.add(this);
isRecordPop.add(false);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
return true;
}其实就是加入FragmentManager的队列而已.继续看:
private void scheduleCommit() {
synchronized (this) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}mHost.getHandler()其实就是FragmentActivity中的mHandler了,先移除,确保没有该Callback,然后加入Callback.看下具体实现:
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};public boolean execPendingActions() {
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
return didSomething;
}再回头看下commitNow()和commitNowAllowingStateLoss()方法,就是设置禁止加入返回栈,然后execSingleAction方法和execPendingActions()几乎一模一样,从这里看出commit和commitNow()的区别就是一个需要handler队列来执行,一个直接执行,allowStateLoss还是代表是否检测.
@Override
public FragmentTransaction disallowAddToBackStack() {
if (mAddToBackStack) {
throw new IllegalStateException(
"This transaction is already being added to the back stack");
}
mAllowAddToBackStack = false;
return this;
}
public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
ensureExecReady(allowStateLoss);
if (action.generateOps(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
}
doPendingDeferredStart();
}看下generateOpsForPendingActions(mTmpRecords, mTmpIsPop):
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isPop) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
return false;
}
numActions = mPendingActions.size();
for (int i = 0; i < numActions; i++) {
mPendingActions.get(i).generateOps(records, isPop);
}
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
return numActions > 0;
}其实就是执行了上面的generateOps方法,而且mPendingActions执行结束被清空了。
其他代码有点繁多,自己有情趣可以去看看,现在重点来看 doPendingDeferredStart():
void doPendingDeferredStart() {
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();
}
}
}void startPendingDeferredFragments() {
if (mActive == null) return;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
performPendingDeferredStart(f);
}
}
}public void performPendingDeferredStart(Fragment f) {
if (f.mDeferStart) {
if (mExecutingActions) {
// Wait until we're done executing our pending transactions
mHavePendingDeferredStart = true;
return;
}
f.mDeferStart = false;
moveToState(f, mCurState, 0, 0, false);
}
}由于能力有限,就直接讲最重要的 moveToState(f, mCurState, 0, 0, false)方法了.
讲这个之前,首先得先讲Fragment如何和Activity生命周期联系起来.
看下FragmentActivity的onCreate方法:
protected void onCreate(@Nullable Bundle savedInstanceState) {
//代码省略..
mFragments.dispatchCreate();
}
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
public void dispatchCreate() {
mStateSaved = false;
mExecutingActions = true;
moveToState(Fragment.CREATED, false);
mExecutingActions = false;
}
void moveToState(int newState, boolean always) {
//代码省略..
mCurState = newState;
//代码省略..
if (!loadersRunning) {
startPendingDeferredFragments();
}
//代码省略..
}
mCurState就是activity当前的生命周期了,然后又调用startPendingDeferredFragments()最终还是到moveToState(f, mCurState, 0, 0, false)方法了,其他生命周期同理.
moveToState代码量有点多,我就省略大部分代码了,所以只讲下create流程了.
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
//mContainerId就是add(int containerId,Fragment fragment)传进来的布局id,
if (f.mContainerId != 0) {
if (f.mContainerId == View.NO_ID) {
throwException(new IllegalArgumentException(
"Cannot create fragment "
+ f
+ " for a container view with no id"));
}
//mContainer.onFindViewById等同HostCallbacks.onFindViewById(int id),
//也就是FragmentActivity.this.findViewById(id) container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (NotFoundException e) {
resName = "unknown";
}
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ resName
+ ") for fragment " + f));
}
}
f.mContainer = container;
//执行onCreateView方法,
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (Build.VERSION.SDK_INT >= 11) {
ViewCompat.setSaveFromParentEnabled(f.mView, false);
} else {
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
}
//这里把返回的view添加进activity的container中,这里引出一个问题,以前碰到过在
// onCreateView中设置View view = inflater.inflate(R.layout.fragment_page, container, //true);
//会直接蹦,原因就在这里了,因为设置为true就将子类添加进父类了,然后这里又进行一次添加操作,就抛出异常了 if (container != null) {
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(View.GONE);
}
//执行onViewCreated方法
f.onViewCreated(f.mView, f.mSavedFragmentState);
//这里如果用户设置过registerFragmentLifecycleCallbacks,就回调对应的方法.
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
&& f.mContainer != null;
} else {
f.mInnerView = null;
}
}
//执行onActivityCreated方法,然后同理回调
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}我觉得以后多Fragment开发可能会越来越火,了解一下Fragment的基本流程,还是挺重要的吧。由于能力有限,我只是讲下Fragment的流程的一点毛皮,如有错误还望指出。
顺便推荐下一个大神写的Fragment框架:github.com/YoKeyword/F…