简介
FragmentFragmentTransactionFragmentTransaction的实现是
BackStackRecord
,本身也是
Runnable
。FragmentManagerFragmentManager的实现是
FragmentManagerImpl
。Fragment的attach和show的前提都是先用
add
R.id.xxx
,不然怎么show的出来。attach是attach之前detach的东西,show是show之前hidden的东西,一切的前提是已经 add了.做优化使用事先生成的Fragment,那就都add,然后hidden。
FragmentManager fragment = getSupportFragmentManager();
FragmentTransaction transaction = fragment.beginTransaction();
HomeFragment homeFragment = new HomeFragment();
transaction.replace(R.id.main_fragment, homeFragment).addToBackStack("main").commit();
BackStackRecord
Activity里的back stack是由
BackStackRecord
负责操作的,也是Fragment的添加删除从这里开始的。
1
2
3 | final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, Runnable{
} |
1
2
3456789101112131415161718192021222324252627 | //BackStackRecord
public int commit() {
return commitInternal(false);
}
public int commitAllowingStateLoss() {
return commitInternal(true);
}
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);
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
//添加任务
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
} |
1
2
3456789101112131415161718192021 | //FragmentManger
//将一个任务添加到挂起的队列中
public void enqueueAction(Runnable 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<Runnable>();
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
//跑一个Runnable,不过是主线程
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
} |
1
2
34567 | //FragmentManger
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
}; |
1
2
345678910 | //FragmentManger
public boolean execPendingActions() {
......
//跑回BackStackRecord去执行run()
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
mTmpActions[i].run();
mTmpActions[i] = null;
}
} |
1
2
3456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 | //BackStackRecord
public void run() {
......
switch (op.cmd) {
case OP_ADD: {
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
//如果是add添加,又跑到FragmentManger的addFragment
mManager.addFragment(f, false);
} break;
case OP_REPLACE: {
Fragment f = op.fragment;
int containerId = f.mContainerId;
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 (old.mContainerId == containerId) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
old.mNextAnim = exitAnim;
if (mAddToBackStack) {
old.mBackStackNesting += 1;
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
+ old + " to " + old.mBackStackNesting);
}
mManager.removeFragment(old, transition, transitionStyle);
}
}
}
}
if (f != null) {
f.mNextAnim = enterAnim;
mManager.addFragment(f, false);
}
} break;
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.removeFragment(f, transition, transitionStyle);
} break;
case OP_HIDE: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.hideFragment(f, transition, transitionStyle);
} break;
case OP_SHOW: {
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
mManager.showFragment(f, transition, transitionStyle);
} break;
case OP_DETACH: {
Fragment f = op.fragment;
f.mNextAnim = exitAnim;
mManager.detachFragment(f, transition, transitionStyle);
} break;
case OP_ATTACH: {
Fragment f = op.fragment;
f.mNextAnim = enterAnim;
mManager.attachFragment(f, transition, transitionStyle);
} break;
default: {
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
}
} |
1
2
34567891011121314151617181920212223 | //FragmentManger
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
//add 进来的 一般是false
moveToState(fragment);
}
}
} |
1
2
34 | //FragmentManger
void moveToState(Fragment f) {
moveToState(f, mCurState, 0, 0, false);
} |
1
2
345678 | //FragmentManger
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
......
//调用Fragment的onAttach()
f.onAttach(mHost.getContext());
......
} |
1
2
34567891011121314 | /**
* Called when a fragment is first attached to its context.
* {@link #onCreate(Bundle)} will be called after this.
*/
// Fragment
public void onAttach(Context context) {
mCalled = true;
final Activity hostActivity = mHost == null ? null : mHost.getActivity();
if (hostActivity != null) {
mCalled = false;
//关联到hostActivity
onAttach(hostActivity);
}
} |
1
2
34567891011 | /**
* Called when a fragment is first attached to its activity.
* {@link #onCreate(Bundle)} will be called after this.
* <p>Deprecated. See {@link #onAttach(Context)}.
*/
//Fragment
//关联结束
@Deprecated
public void onAttach(Activity activity) {
mCalled = true;
} Fragment 如何实现类似Activity的退栈和压栈的功能 ?Fragment 的事物管理器内部维持了一个双向链表,该结构可以记录我们每次add的Fragment和replace的Fragment,当我们点击back按钮时自动帮我们完成退栈操作transaction.addToBackStack("name");//实现源码在BackStackRecord 中public FragmentTransaction addToBackStack(String name) {if (!mAllowAddToBackStack) {throw new IllegalStateException("This FragmentTransaction is not allowed to be added to the backstack.");}mAddToBackStack = true;mName = name;return this;}//上面的源码仅仅做了一个标记/*** Take care of popping the fragment back stack or finishing the activity* as appropriate.*/public void onBackPressed() {if (!mFragments.popBackStackImmediate()) {finish();}}//mFragments 的原型是FragmentManagerImpl,看看这个方法都干嘛了@Overridepublic boolean popBackStackImmediate() {checkStateLoss();executePendingTransactions();return popBackStackState(mActivity.mHandler, null, -1, 0);}//看看popBackStackState 方法都干了啥,其实通过名称也能大概了解只给几个片段吧,代码太多了while (index >= 0) {//从后退栈中取出当前记录对象BackStackRecord bss = mBackStack.get(index);if (name != null && name.equals(bss.getName())) {break;}if (id >= 0 && id == bss.mIndex) {break;}index--;}Fragment 如何实现类似Activity的退栈和压栈的功能 ?Fragment 的事物管理器内部维持了一个双向链表,该结构可以记录我们每次add的Fragment和replace的Fragment,当我们点击back按钮时自动帮我们完成退栈操作transaction.addToBackStack("name");//实现源码在BackStackRecord 中public FragmentTransaction addToBackStack(String name) {if (!mAllowAddToBackStack) {throw new IllegalStateException("This FragmentTransaction is not allowed to be added to the backstack.");}mAddToBackStack = true;mName = name;return this;}//上面的源码仅仅做了一个标记/*** Take care of popping the fragment back stack or finishing the activity* as appropriate.*/public void onBackPressed() {if (!mFragments.popBackStackImmediate()) {finish();}}//mFragments 的原型是FragmentManagerImpl,看看这个方法都干嘛了@Overridepublic boolean popBackStackImmediate() {checkStateLoss();executePendingTransactions();return popBackStackState(mActivity.mHandler, null, -1, 0);}//看看popBackStackState 方法都干了啥,其实通过名称也能大概了解只给几个片段吧,代码太多了while (index >= 0) {//从后退栈中取出当前记录对象BackStackRecord bss = mBackStack.get(index);if (name != null && name.equals(bss.getName())) {break;}if (id >= 0 && id == bss.mIndex) {break;}index--;} |