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按钮时自动帮我们完成退栈操作
//实现源码在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按钮时自动帮我们完成退栈操作
//实现源码在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
- Fragment简析
- Fragment
- Fragment
- fragment
- Fragment
- Fragment
- Fragment
- Fragment
- fragment
- fragment
- Fragment
- Fragment
- fragment
- Fragment
- Fragment
- Fragment
- Fragment
- Fragment
- 迷宫问题(深搜
- nginx配置的详细信息
- JS实现静态页面之间的参数传递
- 【Android 开发工具】px和dp转换工具
- jenkins执行shell启动tomcat失败
- Fragment简析
- 转载 分页jquery,插件
- 各种数据类型的取值范围
- linux 基本命令
- Servlet_09_ServletContext(续1)
- Android Framework
- Problem A+B(Big Integer)大数相加
- 子类不能抛新的异常
- java匿名类没有函数名的花括号