Fragment简析

来源:互联网 发布:数据库表怎么设计 编辑:程序博客网 时间:2024/06/01 09:48

简介

  • Fragment
  • FragmentTransaction
    FragmentTransaction的实现是BackStackRecord,本身也是Runnable
  • FragmentManager
    FragmentManager的实现是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的添加删除从这里开始的。

123
final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, Runnable{}
123456789101112131415161718192021222324252627
//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;   }
123456789101112131415161718192021
//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);           }       }   }
1234567
//FragmentManger   Runnable mExecCommit = new Runnable() {       @Override       public void run() {           execPendingActions();       }   };
12345678910
//FragmentManger   public boolean execPendingActions() {......//跑回BackStackRecord去执行run() mExecutingActions = true;           for (int i=0; i<numActions; i++) {               mTmpActions[i].run();               mTmpActions[i] = null;           }}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
//BackStackRecordpublic 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);                }            }
1234567891011121314151617181920212223
//FragmentMangerpublic 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);            }        }    }
1234
//FragmentManger   void moveToState(Fragment f) {       moveToState(f, mCurState, 0, 0, false);   }
12345678
//FragmentManger    void moveToState(Fragment f, int newState, int transit, int transitionStyle,            boolean keepActive) {            ......            //调用Fragment的onAttach()f.onAttach(mHost.getContext());......}
1234567891011121314
/** * Called when a fragment is first attached to its context. * {@link #onCreate(Bundle)} will be called after this. */ // Fragmentpublic void onAttach(Context context) {    mCalled = true;    final Activity hostActivity = mHost == null ? null : mHost.getActivity();    if (hostActivity != null) {        mCalled = false;        //关联到hostActivity        onAttach(hostActivity);    }}


1234567891011
/** * 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  //关联结束@Deprecatedpublic 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 back
stack.");
}m
AddToBackStack = 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,看看这个方法都干嘛了
@Override
public 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;
}i
ndex--;
}
  • 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 back
stack.");
}m
AddToBackStack = 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,看看这个方法都干嘛了
@Override
public 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;
}i
ndex--;
}
0 0
原创粉丝点击