当咱们点击了返回键,首先收到消息的仍是activity,若是回退栈有fragment,则有fragment manager处理, 不然调用finish():java
//in class Activity /** * Called when the activity has detected the user's press of the back * key. The default implementation simply finishes the current activity, * but you can override this to do whatever you want. */ public void onBackPressed() { if (!mFragments.popBackStackImmediate()) { finish(); } }
在FragmentManager中(由FragmentManagerImp实现),首先将事务队列里还没有执行的事务执行完毕, 而后处理回退操做。实际使用的时候,时常能够看到这样的场景:点击一个按钮(会跳转到另外一个fragment或activity)而后立刻点击回退,能够感觉到屏幕的闪烁, 在性能稍差的设备上尤为明显, 其实这些现象均可以在这里找到答案。ide
@Override public boolean popBackStackImmediate() { checkStateLoss(); executePendingTransactions(); return popBackStackState(mActivity.mHandler, null, -1, 0); }
这里操做的是事务记录,虽然感受像是操做的fragment。弹出事务时, 能够是弹出一个,也能够根据条件弹出多个(能够认为控制mBackStack的容量),而后对栈顶的事务执行恢复显示:即调用改事务的 popFromBackStack(boolean doStateMove)方法。性能
boolean popBackStackState(Handler handler, String name, int id, int flags) { if (mBackStack == null) { return false; } if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) { int last = mBackStack.size()-1; if (last < 0) { return false; } final BackStackRecord bss = mBackStack.remove(last); bss.popFromBackStack(true); reportBackStackChanged(); } else { int index = -1; if (name != null || id >= 0) { // If a name or ID is specified, look for that place in // the stack. index = mBackStack.size()-1; while (index >= 0) { BackStackRecord bss = mBackStack.get(index); if (name != null && name.equals(bss.getName())) { break; } if (id >= 0 && id == bss.mIndex) { break; } index--; } if (index < 0) { return false; } if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) { index--; // Consume all following entries that match. while (index >= 0) { BackStackRecord bss = mBackStack.get(index); if ((name != null && name.equals(bss.getName())) || (id >= 0 && id == bss.mIndex)) { index--; continue; } break; } } } if (index == mBackStack.size()-1) { return false; } final ArrayList<BackStackRecord> states = new ArrayList<BackStackRecord>(); for (int i=mBackStack.size()-1; i>index; i--) { states.add(mBackStack.remove(i)); } final int LAST = states.size()-1; for (int i=0; i<=LAST; i++) { if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i)); states.get(i).popFromBackStack(i == LAST); } reportBackStackChanged(); } return true; }
最后是BackStackRecord的 popFromBackStack方法, 和BackStackRecord的 run() 方法是相对应的, 最后仍是要经过FragmentManager的 moveToState来执行实际的处理(激活fragment的生命周期方法)this
public void popFromBackStack(boolean doStateMove) { if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "popFromBackStack: " + this); LogWriter logw = new LogWriter(TAG); PrintWriter pw = new PrintWriter(logw); dump(" ", null, pw, null); } bumpBackStackNesting(-1); Op op = mTail; while (op != null) { switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; f.mNextAnim = op.popExitAnim; mManager.removeFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_REPLACE: { Fragment f = op.fragment; if (f != null) { f.mNextAnim = op.popExitAnim; mManager.removeFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } if (op.removed != null) { for (int i=0; i<op.removed.size(); i++) { Fragment old = op.removed.get(i); old.mNextAnim = op.popEnterAnim; mManager.addFragment(old, false); } } } break; case OP_REMOVE: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.addFragment(f, false); } break; case OP_HIDE: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.showFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_SHOW: { Fragment f = op.fragment; f.mNextAnim = op.popExitAnim; mManager.hideFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_DETACH: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.attachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_ATTACH: { Fragment f = op.fragment; f.mNextAnim = op.popEnterAnim; mManager.detachFragment(f, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; default: { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); } } op = op.prev; } if (doStateMove) { mManager.moveToState(mManager.mCurState, FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); } if (mIndex >= 0) { mManager.freeBackStackIndex(mIndex); mIndex = -1; } }