您的位置:首页 > 其它

Fragment简析

2016-02-26 15:49 281 查看

简介

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--;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: