- 论坛徽章:
- 80
|
FragmentManager 是一个抽象类,实现类是 FragmentManagerImpl ,跟 FragmentManager 在同一个类文件里。FragmentTransaction 也是一个抽象类,具体实现是 BackStackRecord 。BackStackRecord 其实是一个封装了一个队列。咱们看 add 方法和 replace 方法。
add 方法和 replace 方法都是把一个操作 OP_XX 放入到队列里,Op 是其内部封装的一个操作的类。在 BackStackRecord 的 run 方法里,每次会从队列的头(mHead)获取一个操作 Op ,如果 Op 操作是 add ,则调用 FragmentManager 的 addFragment() 方法,如果 Op 操作是 replace ,则先调用 FragmentManager 的 removeFragment() 方法,然后再调用 addFragment() 方法。
下面是 add 方法。- public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
- doAddOp(containerViewId, fragment, tag, OP_ADD);
- return this;
- }
复制代码 下面是 replace 方法。- 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;
- }
复制代码 add 和 replace 方法都是调用的 doAddOp 方法。也就是把一个操作 Op 添加到队列。- private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- 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 (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);
- }
复制代码 run 方法才是真正执行的方法。什么时候执行先不考虑,只需要知道一系列的操作会一次执行,而不是一个操作执行一次。
run 方法有点大,就看一下 while 循环开始和结束的时候,以及 switch case 里 OP_ADD 和 OP_REPLACE 分支就可以了。- public void run() {
- if (FragmentManagerImpl.DEBUG) {
- Log.v(TAG, "Run: " + this);
- }
- if (mAddToBackStack) {
- if (mIndex < 0) {
- throw new IllegalStateException("addToBackStack() called after commit()");
- }
- }
- bumpBackStackNesting(1);
- SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
- SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
- calculateFragments(firstOutFragments, lastInFragments);
- beginTransition(firstOutFragments, lastInFragments, false);
- // 获取队列的头
- Op op = mHead;
- while (op != null) {
- switch (op.cmd) {
- case OP_ADD: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);//添加
- }
- break;
- case OP_REPLACE: {
- Fragment f = op.fragment;
- 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 (f == null || old.mContainerId == f.mContainerId) {
- if (old == f) {
- op.fragment = f = null;
- } else {
- if (op.removed == null) {
- op.removed = new ArrayList<Fragment>();
- }
- op.removed.add(old);
- old.mNextAnim = op.exitAnim;
- if (mAddToBackStack) {
- old.mBackStackNesting += 1;
- if (FragmentManagerImpl.DEBUG) {
- Log.v(TAG, "Bump nesting of "
- + old + " to " + old.mBackStackNesting);
- }
- }
- mManager.removeFragment(old, mTransition, mTransitionStyle);//删除
- }
- }
- }
- }
- if (f != null) {
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);//添加
- }
- }
- break;
- case OP_REMOVE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.removeFragment(f, mTransition, mTransitionStyle);
- }
- break;
- case OP_HIDE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.hideFragment(f, mTransition, mTransitionStyle);
- }
- break;
- case OP_SHOW: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.showFragment(f, mTransition, mTransitionStyle);
- }
- break;
- case OP_DETACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.detachFragment(f, mTransition, mTransitionStyle);
- }
- break;
- case OP_ATTACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.attachFragment(f, mTransition, mTransitionStyle);
- }
- break;
- default: {
- throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
- }
- }
- op = op.next;//队列的下一个
- }
- mManager.moveToState(mManager.mCurState, mTransition,
- mTransitionStyle, true);
- if (mAddToBackStack) {
- mManager.addBackStackState(this);
- }
- }
复制代码 BackStackRecord 的构造器里参数列表里有一个 FragmentManager ,所有 BackStackRecord 其实是有一个 FragmentManager 的引用的,BackStackRecord 可以直接调用 FragmentManager 的 addFragment 方法。
下面是 FragmentManager 的 addFragment() 方法,每次 add 一个 Fragment,Fragment 对象都会被放入到 mAdded 的容器里。- public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- boolean show = false;
- ArrayList<Fragment> newMenus = null;
- if (mAdded != null) {
- for (int i=0; i<mAdded.size(); i++) {
- Fragment f = mAdded.get(i);
- if (f != null) {
- if (f.performCreateOptionsMenu(menu, inflater)) {
- show = true;
- if (newMenus == null) {
- newMenus = new ArrayList<Fragment>();
- }
- newMenus.add(f);
- }
- }
- }
- }
-
- if (mCreatedMenus != null) {
- for (int i=0; i<mCreatedMenus.size(); i++) {
- Fragment f = mCreatedMenus.get(i);
- if (newMenus == null || !newMenus.contains(f)) {
- f.onDestroyOptionsMenu();
- }
- }
- }
-
- mCreatedMenus = newMenus;
-
- return show;
- }
复制代码 |
|