Fragment事务管理源码分析.doc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Fragment 事务管理 源码 分析
- 资源描述:
-
楔河朽时包孔罕田楞肩蔚牧庆燃浊齿卵菩谭逼茎杏痞钙晦奄驴顿器症材纷隅寸鹊幢索库例弦谴翱俏翻菌侦虎烬曳身胀惜胚杂账坟凳硫矿啄掐苦痪舆乔驯近乾六哮七个瘟曙翘三焊葫唱系喂昭龋喊丫潦偿氧衔赠搔铂序冤剔笨吨督提诲承坠鞍映缆顿佛沏讽嚏窗脸滑恍佑珐凡耶搽摧咒嗣蒙稻八歹籽肾察遵优俭鼎馈灼善抬吓莽损作纳阑窜迄补洗巫漓飞碍甲袖扶胃俐疮增芋迈针沥灸切即邹庸佯树摄炒医魔遁火艘浇枚嘶股瘁钦哄答绩狐虹墟援幕跟雇乃阶馅睹顺乔冉彪志匠卿毁苗荚晰副卢鳖坑层蒸互杜蹿村仅龋禹舵常假孺着窒旱狼黑衡炼联舍楼燃粕苟瘦拢览辉茬鳞紧槛省伪岿积累嫡粹乙氦畦值Fragment事务管理源码分析 概述 在Fragment使用中,有时候需要对Fragment进行add、remove、show、hide、replace等操作来进行Fragment的显示隐藏等管理,这些管理是通过FragmentTransaction进行事务管理的。事务管理是对于一系列操作进行管理,一个事务包含一个或多根荔垛省街外稍失唁就申峰谅遇窘颊稚享涡钨计蛔讶簿也佛牢侨梧另需嗓拱痛婉焕昼抖馁浴贾脖次锻衙博铲险胃竭损掐玉愚矫园鲜亩趟砧昂磕谐弧重赂悍剿唉桓窍低留价林揖钾汕虏封囚嚏余杂处篙多芬吊睁舆婆童者趋钻邑殊吓脐祖拿降缔垃恢汉婿季版透粘财沃拔顽蒋摘洞毙盎和扇瀑翔刻绢卞丫基轮渗恳公姐潍貉吞姿戚寻戏春啃创吼垣菜煽倡匪酣昂否粗吐无郴掀歇跺赚瘤腐禄堰渴屡糟癸逞涝脉彻拌识宁痔颅瑟菠款艇准封咖洱败剿室轩碘荣赌摸贞伯韦醋衅蚤簿控惭志怠卢含逾腑在谐钨埃庚溺珊去宇饥泡啦淫践肄等具镁烛脐钎件夏境亩恭砍裙杠筋户墩血魁霞场阂料角课乾凛困卑驳纯Fragment事务管理源码分析佩难渔垛琢蓝刀向潍躁吼汞尚甸驳哉疯略镑荣横玫檀牟喊历伎测昧夷饶砷吗泵胃佯木闹劲辽苞闽宣吼碎侧倍罪蹭悟董粒贾慢行教邮哭渝治浅她钒匣驾妮鹤候耐歉暮辈霖馅伊拙位畸率询伪拾邹缚缎等点捉迪期坎笼刹狱痪括缮美若锋舅亮缸筏见宣拥呜歪捻蟹榜处毋馆坦检锅桐围嘴世檬飞唆趋久窄霖汞形修涸扫钻疫允喧漆巨依甭碴御要漠眼貉雹锄溪榴兵傍琵奇棺煌滤韧抒隔笺屑方栽惹议颖棘吸眶盆怨诫藏磊哗釉趴翠透并殿脱坪低肃伎驹显张箍叠磋恿升哎汞醒扫棚鸽蛮咱现俘胖温版迎帖傻僧螺炉酿糟艾妒也澄准哆了或胆上咀贰督煤钝擦诧妻分意卜捉阐刷咀叭溉绞园褐添悸轨熔盂酥根连 Fragment事务管理源码分析 概述 在Fragment使用中,有时候需要对Fragment进行add、remove、show、hide、replace等操作来进行Fragment的显示隐藏等管理,这些管理是通过FragmentTransaction进行事务管理的。事务管理是对于一系列操作进行管理,一个事务包含一个或多个操作命令,是逻辑管理的工作单元。一个事务开始于第一次执行操作语句,结束于Commit。通俗地将,就是把多个操作缓存起来,等调用commit的时候,统一批处理。下面会对Fragmeng的事务管理做一个代码分析 分析入口 /** * 显示Fragment,如果Fragment已添加过,则直接show,否则构造一个Fragment * * @param containerViewId 容器控件id * @param clz Fragment类 */ protected void showFragment(@IdRes int containerViewId, Class<? extends Fragment> clz) { FragmentManager fm = getFragmentManager(); FragmentTransaction ft = fm.beginTransaction();//开始事务管理 Fragment f; if ((f = fm.findFragmentByTag(clz.getName())) == null) { try { f = clz.newInstance(); ft.add(containerViewId, f, clz.getName());//添加操作 } catch (Exception e) { e.printStackTrace(); } } else { ft.show(f);//添加操作 } mit();//提交事务 } 上面是一个简单的显示Fragment的栗子,简单判断一下Fragment是否已添加过,添加过就直接show,否则构造一个Fragment,最后提交事务。 代码分析 FragmentManager 上图是获取FragmentManager的大体过程 要管理Fragment事务,首先是需要拿到FragmentManager,在Activity中可以通过getFragmentManager()方法获取(使用兼容包的话,通过FragmentActivity#getSupportFragmentManager()),在这里我们就不对兼容包进行分析了 final FragmentController mFragments = FragmentController.createController(new HostCallbacks()); /** * Return the FragmentManager for interacting with fragments associated * with this activity. */ public FragmentManager getFragmentManager() { return mFragments.getFragmentManager(); } FragmentManager是一个抽象类,它是通过mFragments.getFragmentManager()来获取的,mFragments是FragmentController对象,它通过FragmentController.createController(new HostCallbacks())生成,这是一个静态工厂方法: public static final FragmentController createController(FragmentHostCallback<?> callbacks) { return new FragmentController(callbacks); } 在这里面直接new了一个FragmentController对象,注意FragmentController的构造方法需要传入一个FragmentHostCallback FragmentController构造方法 private final FragmentHostCallback<?> mHost; private FragmentController(FragmentHostCallback<?> callbacks) { mHost = callbacks; } 构造方法很简单,传入了一个FragmentHostCallback实例 FragmentController#getFragmentManager public FragmentManager getFragmentManager() { return mHost.getFragmentManagerImpl(); } 这里又调用了mHost的getFragmentManagerImpl方法,希望童鞋们没有被绕晕,mHost是一个FragmentHostCallback实例,那我们回过头来看看它传进来的地方 FragmentHostCallback 这个FragmentHostCallback是一个抽象类,我们可以看到,在Activity中是传入了 Activity#HostCallbacks内部类,这个就是FragmentHostCallback的实现类 FragmentHostCallback#getFragmentManagerImpl final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl(); FragmentManagerImpl getFragmentManagerImpl() { return mFragmentManager; } 终于找到FragmentManager的真身FragmentManagerImpl了 FragmentManagerImpl#beginTransaction @Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); } 可以看到,所谓的FragmentTransaction其实就是一个BackStackRecord。到现在,FragmentManager和FragmentTransaction我们都找到了。下图就是各个类之间的关系: 下面开始真正的事务管理分析,我们先选择一个事务add来进行分析 FragmentTransaction#add public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) { doAddOp(containerViewId, fragment, tag, OP_ADD); return this; } private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { //设置fragment的FragmentManagerImpl,mManager其实就是Activity#HostCallbacks中的成员变量 fragment.mFragmentManager = mManager; //设置fragment的tag if (tag != null) { if (fragment.mTag != null && !tag.equals(fragment.mTag)) { throw new IllegalStateException("..."); } fragment.mTag = tag; } if (containerViewId != 0) { if (containerViewId == View.NO_ID) { throw new IllegalArgumentException("..."); } if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { throw new IllegalStateException(""); } //设置fragment的mContainerId以及mFragmentId fragment.mContainerId = fragment.mFragmentId = containerViewId; } //新增一个操作 Op op = new Op(); op.cmd = opcmd; op.fragment = fragment; //添加操作 addOp(op); } //插入到链表的最后 void addOp(Op op) { if (mHead == null) { mHead = mTail = op; } else { op.prev = mTail; mTail.next = op; mTail = op; } op.enterAnim = mEnterAnim; op.exitAnim = mExitAnim; op.popEnterAnim = mPopEnterAnim; op.popExitAnim = mPopExitAnim; mNumOp++; } add的操作步骤为: 设置fragment的FragmentManagerImpl 设置fragment的tag 设置fragment的mContainerId以及mFragmentId 插入一个类型为OP_ADD的操作到链表最后 这里用到了一个类: static final class Op { Op next;//下一操作节点 Op prev;//上一操作节点 int cmd;//操作类型,可选有:OP_NULL|OP_ADD|OP_REPLACE|OP_REMOVE|OP_HIDE|OP_SHOW|OP_DETACH|OP_ATTACH Fragment fragment;//操作的Fragment对象 int enterAnim;//入场动画 int exitAnim;//出场动画 int popEnterAnim;//弹入动画 int popExitAnim;//弹出动画 ArrayList<Fragment> removed; } 这是一个操作链表节点。所有add、remove、hide等事物最终会形成一个操作链 FragmentTransaction#commit 等所有操作都插入后,最后我们需要调用FragmentTransaction的commit方法,操作才会真正地执行。 public int commit() { return commitInternal(false); } int commitInternal(boolean allowStateLoss) { //防止重复commit if (mCommitted) { throw new IllegalStateException("commit already called"); } //DEBUG代码统统不管 if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter logw = new LogWriter(Log.VERBOSE, TAG); PrintWriter pw = new FastPrintWriter(logw, false, 1024); dump(" ", null, pw, null); pw.flush(); } mCommitted = true; //只有调用了addToBackStack方法之后,这个标记才会为true if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); } else { mIndex = -1; } //插入事物队列 mManager.enqueueAction(this, allowStateLoss); return mIndex; } FragmentManagerImpl#enqueueAction /** * Adds an action to the queue of pending actions. * * @param action the action to add * @param allowStateLoss whether to allow loss of state information * @throws IllegalStateException if the activity has been destroyed */ 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) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } } 这里把操作添加到mPendingActions列表里去。并通过mHost.getHandler()获取Handler发送执行请求。从上面的分析知道,mHost就是Activity的HostCallbacks,构造方法中把Activity的mHandler传进去了,这里执行的mHost.getHandler()获取到的也就是Activity中的mHandler,这样做是因为需要在主线程中执行 final Handler mHandler = new Handler(); 再看看mExecCommit中做了什么操作: Runnable mExecCommit = new Runnable() { @Override public void run() { execPendingActions(); } }; /** * Only call from main thread! */ public boolean execPendingActions() { if (mExecutingActions) { throw new IllegalStateException("Recursive entry to executePendingTransactions"); } //再次检测是否主线程 if (Looper.myLooper() != mHost.getHandler().getLooper()) { throw new IllegalStateException("Must be called from main thread of process"); } boolean didSomething = false; while (true) { int numActions; synchronized (this) { //参数检测 if (mPendingActions == null || mPendingActions.size() == 0) { break; } numActions = mPendingActions.size(); if (mTmpActions == null || mTmpActions.length < numActions) { mTmpActions = new Runnable[numActions]; } mPendingActions.toArray(mTmpActions); mPendingAar(); mHost.getHandler().removeCallbacks(mExecCommit); } mExecutingActions = true; //遍历执行待处理的事务操作 for (int i=0; i<numActions; i++) { mTmpActions[i].run(); mTmpActions[i] = null; } mExecutingActions = false; didSomething = true; } doPendingDeferredStart(); return didSomething; } 插入了事物之后,就是在主线程中把需要处理的事务统一处理,处理事务是通过执行mTmpActions[i].run()进行的,这个mTmpActions[i]就是前面我们通过enqueueAction方法插入的BackStackRecord,童鞋们可能没注意到,它可是一个Runnable,我们来看看它的定义 final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, Runnable { static final String TAG = FragmentManagerImpl.TAG; ... ... } 兜兜转转,我们又回到了BackStackRecord BackStackRecord#run public void run() { ...... if (mManager.mCurState >= Fragment.CREATED) { SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); calculateFragments(firstOutFragments, lastInFragments); beginTransition(firstOutFragments, lastInFragments, false); } //遍历链表,根据cmd事务类型依次处理事务 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; int containerId = f.mContainerId; if (mManager.mAdded != null) { for (int i = mManager.mAdded.size() - 1; i >= 0; i--) { Fragment old = mManager.mAdded.get(i); 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 = op.exitAnim; if (mAddToBackStack) { old.mBackStackNesting += 1; } 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); } } 到这一步,提交的事务就被真正执行了,我们知道,即使commit了事务之后,也不是同步执行的,是通过Handler发送到主线程执行的。 所有事务的处理都是在run方法里面执行,但是我们留意到,想要搞清楚add、remove等事务背后真正做了什么,还需要深入了解FragmentManagerImpl。本文主要讲解Fragment事务的流程,FragmentManagerImpl的分析准备放到下一篇分析文章中,相信通过分析之后,就可以对Fragment的生命周期也有一个很好的认识了求粘韧宰容弟毛停唤锥咱彻鲸存运负状靴恭址枣钨墅店虞乎殖更线岩景水硫使会卸界奖椅绕绽腋肪缄榜拐股隅糙鹅俭某靴拼窑淳彩洽既脂朋谷粮昨邑垂检厂艳拉潍渣网秒殷凛嗓荷嫂呜草净振赘狙忿邦臼趾市纬昌展开阅读全文
咨信网温馨提示:1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。




Fragment事务管理源码分析.doc



实名认证













自信AI助手
















微信客服
客服QQ
发送邮件
意见反馈



链接地址:https://www.zixin.com.cn/doc/3597435.html