目录

1.api

2.流程梳理

2.1 addFragment

2.2 attachFragment

2.3 restoreAllState

3.总结


1.api

/frameworks/base/core/java/android/app/Fragment.java

    /*** Return true if the fragment is currently added to its activity.*/final public boolean isAdded() {return mHost != null && mAdded;}

isAdded表示当前fragment有没有被加入到activity,那add具体是指的什么呢?在哪里被设为true?mAdded在fragment中只有初始化

    // True if the fragment is in the list of added fragments.boolean mAdded;

由于它是个Default权限的,所有只能是同包或者子类有权修改。

2.流程梳理

那么fragment的mAdded的参数只有是FragmentManager会改,看下具体改动的地方

搜了下有3个方法

  • addFragment
  • attachFragment
  • restoreAllState

2.1 addFragment

    public void addFragment(Fragment fragment, boolean moveToStateNow) {if (DEBUG) Log.v(TAG, "add: " + fragment);makeActive(fragment);if (!fragment.mDetached) {if (mAdded.contains(fragment)) {throw new IllegalStateException("Fragment already added: " + fragment);}synchronized (mAdded) {mAdded.add(fragment);}fragment.mAdded = true;fragment.mRemoving = false;if (fragment.mView == null) {fragment.mHiddenChanged = false;}if (fragment.mHasMenu && fragment.mMenuVisible) {mNeedMenuInvalidate = true;}if (moveToStateNow) {moveToState(fragment);}}}

这里可以看到有个mAdded的ArrayList,会将add的fragment加进去,加进去后将fragment的标志位置为true。

    final ArrayList<Fragment> mAdded = new ArrayList<>();

接着看下addFragment哪里有调用

    @Overridepublic View onCreateView(View parent, String name, Context context, AttributeSet attrs) {if (!"fragment".equals(name)) {return null;}String fname = attrs.getAttributeValue(null, "class");TypedArray a =context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);if (fname == null) {fname = a.getString(com.android.internal.R.styleable.Fragment_name);}int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);a.recycle();int containerId = parent != null ? parent.getId() : 0;if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {throw new IllegalArgumentException(attrs.getPositionDescription()+ ": Must specify unique android:id, android:tag, or have a parent with"+ " an id for " + fname);}// If we restored from a previous state, we may already have// instantiated this fragment from the state and should use// that instance instead of making a new one.Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;if (fragment == null && tag != null) {fragment = findFragmentByTag(tag);}if (fragment == null && containerId != View.NO_ID) {fragment = findFragmentById(containerId);}if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"+ Integer.toHexString(id) + " fname=" + fname+ " existing=" + fragment);if (fragment == null) {fragment = mContainer.instantiate(context, fname, null);fragment.mFromLayout = true;fragment.mFragmentId = id != 0 ? id : containerId;fragment.mContainerId = containerId;fragment.mTag = tag;fragment.mInLayout = true;fragment.mFragmentManager = this;fragment.mHost = mHost;fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);addFragment(fragment, true);} else if (fragment.mInLayout) {// A fragment already exists and it is not one we restored from// previous state.throw new IllegalArgumentException(attrs.getPositionDescription()+ ": Duplicate id 0x" + Integer.toHexString(id)+ ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)+ " with another fragment for " + fname);} else {// This fragment was retained from a previous instance; get it// going now.fragment.mInLayout = true;fragment.mHost = mHost;// If this fragment is newly instantiated (either right now, or// from last saved state), then give it the attributes to// initialize itself.if (!fragment.mRetaining) {fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);}}// If we haven't finished entering the CREATED state ourselves yet,// push the inflated child fragment along. This will ensureInflatedFragmentView// at the right phase of the lifecycle so that we will have mView populated// for compliant fragments below.if (mCurState < Fragment.CREATED && fragment.mFromLayout) {moveToState(fragment, Fragment.CREATED, 0, 0, false);} else {moveToState(fragment);}if (fragment.mView == null) {throw new IllegalStateException("Fragment " + fname+ " did not create a view.");}if (id != 0) {fragment.mView.setId(id);}if (fragment.mView.getTag() == null) {fragment.mView.setTag(tag);}return fragment.mView;}

看起来是fragment创建的生命周期有调用。

2.2 attachFragment

    public void attachFragment(Fragment fragment) {if (DEBUG) Log.v(TAG, "attach: " + fragment);if (fragment.mDetached) {fragment.mDetached = false;if (!fragment.mAdded) {if (mAdded.contains(fragment)) {throw new IllegalStateException("Fragment already added: " + fragment);}if (DEBUG) Log.v(TAG, "add from attach: " + fragment);synchronized (mAdded) {mAdded.add(fragment);}fragment.mAdded = true;if (fragment.mHasMenu && fragment.mMenuVisible) {mNeedMenuInvalidate = true;}}}}

这里也是将fragment加进mAdded中去并将fragment的mAdded设为true,但是不同的是可以fragment.mDetached为true的时候才会attach并且没有added.不同于之前addFragment是fragment.mDetached为false才走进来。

看了下attachFragment是只有如下会调用

/frameworks/base/core/java/android/app/BackStackRecord.java

    /*** Executes the operations contained within this transaction. The Fragment states will only* be modified if optimizations are not allowed.*/void executeOps() {final int numOps = mOps.size();for (int opNum = 0; opNum < numOps; opNum++) {final Op op = mOps.get(opNum);final Fragment f = op.fragment;if (f != null) {f.setNextTransition(mTransition, mTransitionStyle);}switch (op.cmd) {case OP_ADD:f.setNextAnim(op.enterAnim);mManager.addFragment(f, false);break;case OP_REMOVE:f.setNextAnim(op.exitAnim);mManager.removeFragment(f);break;case OP_HIDE:f.setNextAnim(op.exitAnim);mManager.hideFragment(f);break;case OP_SHOW:f.setNextAnim(op.enterAnim);mManager.showFragment(f);break;case OP_DETACH:f.setNextAnim(op.exitAnim);mManager.detachFragment(f);break;case OP_ATTACH:f.setNextAnim(op.enterAnim);mManager.attachFragment(f);break;

还有个逆过程

    /*** Reverses the execution of the operations within this transaction. The Fragment states will* only be modified if reordering is not allowed.** @param moveToState {@code true} if added fragments should be moved to their final state*                    in ordered transactions*/void executePopOps(boolean moveToState) {for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {final Op op = mOps.get(opNum);Fragment f = op.fragment;if (f != null) {f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),mTransitionStyle);}switch (op.cmd) {case OP_ADD:f.setNextAnim(op.popExitAnim);mManager.removeFragment(f);break;case OP_REMOVE:f.setNextAnim(op.popEnterAnim);mManager.addFragment(f, false);break;case OP_HIDE:f.setNextAnim(op.popEnterAnim);mManager.showFragment(f);break;case OP_SHOW:f.setNextAnim(op.popExitAnim);mManager.hideFragment(f);break;case OP_DETACH:f.setNextAnim(op.popEnterAnim);mManager.attachFragment(f);break;case OP_ATTACH:f.setNextAnim(op.popExitAnim);mManager.detachFragment(f);break;

看下OP_ATTCH是怎么加进去的

    public FragmentTransaction attach(Fragment fragment) {addOp(new Op(OP_ATTACH, fragment));return this;}void addOp(Op op) {mOps.add(op);op.enterAnim = mEnterAnim;op.exitAnim = mExitAnim;op.popEnterAnim = mPopEnterAnim;op.popExitAnim = mPopExitAnim;}

流程理不顺了,后续打个堆栈看下。

2.3 restoreAllState

restoreAllState看起来是个恢复机制

    void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {// If there is no saved state at all, then there can not be// any nonConfig fragments either, so that is that.if (state == null) return;FragmentManagerState fms = (FragmentManagerState)state;if (fms.mActive == null) return;List<FragmentManagerNonConfig> childNonConfigs = null;// First re-attach any non-config instances we are retaining back// to their saved state, so we don't try to instantiate them again.if (nonConfig != null) {List<Fragment> nonConfigFragments = nonConfig.getFragments();childNonConfigs = nonConfig.getChildNonConfigs();final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;for (int i = 0; i < count; i++) {Fragment f = nonConfigFragments.get(i);if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);int index = 0; // index of f in fms.mActivewhile (index < fms.mActive.length && fms.mActive[index].mIndex != f.mIndex) {index++;}if (index == fms.mActive.length) {throwException(new IllegalStateException("Could not find active fragment "+ "with index " + f.mIndex));}FragmentState fs = fms.mActive[index];fs.mInstance = f;f.mSavedViewState = null;f.mBackStackNesting = 0;f.mInLayout = false;f.mAdded = false;f.mTarget = null;if (fs.mSavedFragmentState != null) {fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(FragmentManagerImpl.VIEW_STATE_TAG);f.mSavedFragmentState = fs.mSavedFragmentState;}}}// Build the full list of active fragments, instantiating them from// their saved state.mActive = new SparseArray<>(fms.mActive.length);for (int i=0; i<fms.mActive.length; i++) {FragmentState fs = fms.mActive[i];if (fs != null) {FragmentManagerNonConfig childNonConfig = null;if (childNonConfigs != null && i < childNonConfigs.size()) {childNonConfig = childNonConfigs.get(i);}Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig);if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);mActive.put(f.mIndex, f);// Now that the fragment is instantiated (or came from being// retained above), clear mInstance in case we end up re-restoring// from this FragmentState again.fs.mInstance = null;}}// Update the target of all retained fragments.if (nonConfig != null) {List<Fragment> nonConfigFragments = nonConfig.getFragments();final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;for (int i = 0; i < count; i++) {Fragment f = nonConfigFragments.get(i);if (f.mTargetIndex >= 0) {f.mTarget = mActive.get(f.mTargetIndex);if (f.mTarget == null) {Log.w(TAG, "Re-attaching retained fragment " + f+ " target no longer exists: " + f.mTargetIndex);f.mTarget = null;}}}}// Build the list of currently added fragments.mAdded.clear();if (fms.mAdded != null) {for (int i=0; i<fms.mAdded.length; i++) {Fragment f = mActive.get(fms.mAdded[i]);if (f == null) {throwException(new IllegalStateException("No instantiated fragment for index #" + fms.mAdded[i]));}f.mAdded = true;if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);if (mAdded.contains(f)) {throw new IllegalStateException("Already added!");}synchronized (mAdded) {mAdded.add(f);}}}// Build the back stack.if (fms.mBackStack != null) {mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);for (int i=0; i<fms.mBackStack.length; i++) {BackStackRecord bse = fms.mBackStack[i].instantiate(this);if (DEBUG) {Log.v(TAG, "restoreAllState: back stack #" + i+ " (index " + bse.mIndex + "): " + bse);LogWriter logw = new LogWriter(Log.VERBOSE, TAG);PrintWriter pw = new FastPrintWriter(logw, false, 1024);bse.dump("  ", pw, false);pw.flush();}mBackStack.add(bse);if (bse.mIndex >= 0) {setBackStackIndex(bse.mIndex, bse);}}} else {mBackStack = null;}if (fms.mPrimaryNavActiveIndex >= 0) {mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);}mNextFragmentIndex = fms.mNextFragmentIndex;}

其中和added相关的就是将缓存的mAdded集合中的fragment清空,从state中重新获取加入

FragmentManagerState fms = (FragmentManagerState)state;
...     // Build the list of currently added fragments.mAdded.clear();if (fms.mAdded != null) {for (int i=0; i<fms.mAdded.length; i++) {Fragment f = mActive.get(fms.mAdded[i]);if (f == null) {throwException(new IllegalStateException("No instantiated fragment for index #" + fms.mAdded[i]));}f.mAdded = true;if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);if (mAdded.contains(f)) {throw new IllegalStateException("Already added!");}synchronized (mAdded) {mAdded.add(f);}}}

3.总结

本地梳理只是粗浅的找了下大概代码位置,待后续打印堆栈继续梳理。

FragmentManager共有3个方法会将isAdded变为true

  • addFragment
  • attachFragment
  • restoreAllState

(一百三十七)梳理fragment的isAdded相关推荐

  1. Android开发笔记(一百三十七)自定义行为Behavior

    协调布局CoordinatorLayout能够让内部的子控件互相配合着移动,这跟以往孤立的控件运动截然不同,协调运动的结果,意味着App画面更加流畅.自然,也更符合日常生活中的动作场景.如果你对Coo ...

  2. Linux图形管理框架gdm3、lightdm、sddm、kdm介绍(一百三十七)

    1.Gnome系列图形管理器:gdm.gdm3 sudo apt-get install gdm3 Ubuntu默认界面管理器:gdm3 2.KDE系列图形管理器:KDM,SDDM LUbuntu默认 ...

  3. python 保存文件 吃内存_孤荷凌寒自学python第三十七天python的文件与内存变量之间的序列化与反序列化...

    孤荷凌寒自学python第三十七天python的文件与内存变量之间的序列化与反序列化 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.什么是序列化与反序列化 序列化是指将内存中的数据进行指 ...

  4. 四库全书总目提要 卷一百八十四 集部三十七

    四库全书总目提要 卷一百八十四 集部三十七 2011年08月02日 ○别集类存目十一 △<湖海集>·十三卷(山东巡抚采进本) 国朝孔尚任撰.尚任有<节序同风录>,已著录.尚任官 ...

  5. PCL点云处理之计算三角形的外接圆半径(一百二十七)

    PCL点云处理之计算三角形的外接圆的半径(一百二十七) 一.算法介绍 二.代码实现 三.效果展示 一.算法介绍 给出三角形的三个顶点坐标,计算外接圆的半径,具体代码实现如下: 二.代码实现 #incl ...

  6. Python编程基础:第三十七节 石头剪刀布游戏Rock, Paper, Scissors Game

    第三十七节 石头剪刀布游戏Rock, Paper, Scissors Game 前言 实践 前言 我们这一节的内容主要是对前边学习内容的一个综合应用,以石头,剪刀,布游戏为例讲解列表.随机数.用户输入 ...

  7. OpenCV学习笔记(三十六)——Kalman滤波做运动目标跟踪 OpenCV学习笔记(三十七)——实用函数、系统函数、宏core OpenCV学习笔记(三十八)——显示当前FPS OpenC

    OpenCV学习笔记(三十六)--Kalman滤波做运动目标跟踪 kalman滤波大家都很熟悉,其基本思想就是先不考虑输入信号和观测噪声的影响,得到状态变量和输出信号的估计值,再用输出信号的估计误差加 ...

  8. 三十七、Java集合中的Hashtable

    @Author:Runsen @Date:2020/6/4 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

  9. 三十七、Sql 补充 | 数据库优化

    @Author : By Runsen @Date:2020/5/14 在2020年一月初,也是我大三上的寒假,我开始写书,为什么呢?因为化工原理和化工热力学挂了,我需要重拾自己的自信. 对于一个大学 ...

  10. [Python从零到壹] 三十七.图像处理基础篇之图像融合处理和ROI区域绘制

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

最新文章

  1. Android ViewPager嵌套ViewPager滑动冲突处理方法
  2. CentOS6.3.x86_64安装Trac
  3. OSGi入门篇:模块层
  4. 10个相似图片搜索以图找图的网站
  5. linux 文件系统的管理 (硬盘)
  6. php概率计算_PHP指定概率算法
  7. mysql int()_简单谈谈MySQL中的int(m)
  8. crossdomain.xml配置不当的利用和解决办法
  9. Kubernetes 也有局限性吗?
  10. J-LINK 操作使用指南
  11. Linux下chkconfig命令介绍
  12. 台式计算机日历表,Windows台式电脑怎么设置添加桌面日历透明便签?
  13. concurrenthashmap_ConcurrentHashMap核心原理,这次彻底给整明白了
  14. SQL SERVER 2000 自动下载木马病毒 cmd.exe和ftp.exe解决办法
  15. 跟我做一个可以聊天的 Visual Studio Code 插件
  16. 无法打开计算机桌面图标,桌面图标打不开如何修复?桌面图标无法打开的处理方法...
  17. 漫谈程序员系列:别说“我已经很努力了”
  18. ipcs中的dest是什么意思
  19. STM32【H7】理论——综述、HAL库简述
  20. 微信获取openId

热门文章

  1. 调查显示:SD-WAN部署迅猛增长,MPLS不会消失
  2. java版微信调小i机器人接口说明书_java版微信调用小i机器人
  3. 春季实习生校园招聘总结
  4. 项目工作绩效数据、项目工作绩效信息、项目工作绩效报告
  5. 顶级数学家玩股票胜过巴菲特 被人建议改行(图)
  6. html用九张图片做出九宫图,用ps如何将九张照片做成九宫格?
  7. 计算图片的相似度(深度学习)
  8. css实现半圆(上下左右半圆)
  9. SE5_FALSR超分辨率图像模型移植与测试
  10. [USACO10HOL]赶小猪