Fragment has not been attached yet

Fragment 套 Fragment

在商城项目中使用了 Fragment 套 Fragment的结构,大致框架如下图

MallActivity中FragmentStateAdapter的参数为“this”,SortMallFragment的简单代码如下:

public class SortMallFragment extends Fragment implements View.OnClickListener{... ...@Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {View sortView = inflater.inflate(R.layout.sort_mall_fragment, container, false);... ...sortViewPager2 = sortView.findViewById(R.id.sort_view_pager2);sortViewPager2.setAdapter(fsa);return sortView;}... ...private FragmentManager fm = getChildFragmentManager();private Lifecycle lc =  getLifecycle();private FragmentStateAdapter fsa = new FragmentStateAdapter(fm, lc) {... ...}
}

运行之后崩溃,错误提示如下:

                ... ...
Fragment SortMallFragment{7138fb4} (e5c24c20-127c-4821-9707-9ea4cc48e5e7)} has not been attached yet.at androidx.fragment.app.Fragment.getChildFragmentManager(Fragment.java:980)at com.example.baigyueg.fragment.mallFragment.SortMallFragment.<init>(SortMallFragment.java:183)at com.example.baigyueg.fragment.mallFragment.SortMallFragment.newInstance(SortMallFragment.java:42)at com.example.baigyueg.activity.mall.MallActivity.onCreate(MallActivity.java:97)... ...

网上一顿狂搜,发现有关“Fragment has not been attached yet”的条目很少,并且不太符合本项目的情况,参考价值不大。又反过来研究错误提示,点一下“(Fragment.java:980)”,发现进入了Fragment的源码:

@NonNullfinal public FragmentManager getChildFragmentManager() {if (mHost == null) {throw new IllegalStateException("Fragment " + this + " has not been attached yet.");}return mChildFragmentManager;}

大概意思就是当mHostd = null时,就抛出“Fragment ······has not been attached yet”,否则就生成一个“子FragmentManager”。那Fragment中的这个mHost又是什么“东西呢”?再进一步查mHost,就渐渐坠入“迷雾”了——越查越深,新手,知道的东西太少了!但这一查,也有一些小收获:
1、在Fragment中管理其子Fragment要使用ChildFragmentManager,其生成方法getChildFragmentManager()就在Fragment中,在Fragment中使用(又套Fragment)时直接写成:

FragmentManager fm = getChildFragmentManager();

2、Fragment总是要“寄生”或“附着”在什么东西上,比如寄生在活动上或寄生在碎片上,所以Fragment生命周期第一个回调方法就是onAttach(),即先“附着”上去再往下进行。那么错误提示是不是在说本碎片(SortMallFragment)还没有附着在它的宿主(MallActivity)身上?
好,用Log.d(,)测试一下,结果onAttach()已经被执行,那为什么还提示“has not been attached yet”呢?是不是虽然执行了onAttach(),但仍未附着呢?
之前未套子Fragmeng时,运行并不崩溃,是不是在主碎片(SortMallFragment)中套入了子碎片后引起了崩溃?那好先屏蔽掉所有关于子碎片的代码,再测试,未崩溃,为什么?其实也好理解,主碎片中mHost=null,无法生成子碎片管理器(ChildFragmentManager),所以产生了崩溃。问题又回到了原点:到底什么是mHost?真令人头疼!

再梳理一下:
1、网上搜索此错误提示相关条目少,说明要么是Android的一个bug,可能性小,因为碎片嵌套太常用了,若是bug,早被修复了;要么是自己的代码不符合常规的要求(较奇葩),别人都不这样做,所以少见。
2、必须明确当前探索的方向。当前最明显,最强烈的提示还是官方提示“Fragment has not been attached yet”,那好吧,“网过千遍有漏鱼”,就“认真地”再网搜一遍吧!
这次把心沉下来,一条一条地过!发现有位大神说把子碎片相关代码放入主碎片的onStart()方法中可能会解决问题,之前已经搜到过这位大神的建议,但没没有认真思考,就放过去了,好吧,再试试。

public class SortMallFragment extends Fragment implements View.OnClickListener{... ...@Overridepublic void onStart() {super.onStart();FragmentManager fm = getChildFragmentManager();Lifecycle lc =  getLifecycle();FragmentStateAdapter fsa = new FragmentStateAdapter(fm, lc)}@Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {View sortView = inflater.inflate(R.layout.sort_mall_fragment, container, false);... ...sortViewPager2 = sortView.findViewById(R.id.sort_view_pager2);sortViewPager2.setAdapter(fsa);return sortView;} ... ...
}

结果,真神奇,居然没有崩溃, 顺利地进入了子碎片,真令人欣喜,困扰多天的问题就这样解决了!欣喜之余又想,为什么是放在onStart()中,放在碎片的其它回调方法中行不?于是又测试放在onCreateView()、onViewCreated()、onActivityCreated()中,也行,那问题来了,到底放在哪个方法更好呢?通过查看developers网站ViewPager2中的“用户指南”中的代码示例发现,官方只将启动布局文件,并返回对应的view的代码放在onCreateView()中,将生成生成适配器、设置设配器的代码都放在了onViewCreated()中。此两方法前者返回的view就是后者参数中的view。那好吧,比葫芦画瓢,老老实实按官方推荐的去做吧:

public class SortMallFragment extends Fragment implements View.OnClickListener{... ...@Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {View sortView = inflater.inflate(R.layout.sort_mall_fragment, container, false); return  sortView;  } @Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {... ...sortViewPager2 = view.findViewById(R.id.sort_view_pager2);FragmentManager fm = getChildFragmentManager();Lifecycle lc =  getLifecycle();FragmentStateAdapter fsa = new FragmentStateAdapter(fm, lc)sortViewPager2.setAdapter(fsa);}... ...
}

问题解决。那到底是什么原因造成“Fragment has not been attached yet”?仔细观察最上面的代码会发现如下代码:

    private FragmentManager fm = getChildFragmentManager();private Lifecycle lc =  getLifecycle();private FragmentStateAdapter fsa = new FragmentStateAdapter(fm, lc) {... ...}

写在了在回调方法之外,问题就出在这里。在“活”的类(如活动、碎片)中,对象的声明写在回调方法之外,对象的实现(get、set、new等)写在回调方法中,或者干脆声明、实现全部写在回调方法中,这是常识,而我违反了这个常识,将子碎片管理器、主碎片的适配器的声明、实现都写在了回调方法之外。我在想,其中的机理是不是这样的:这些对象的生成往往需要回调方法所在的“活体系”运行时产生的某些数据,不放入这个体系中,就得不到这些数据,产生对象就是“不完美的”,或“过时的”,从而引起报错?总之,在活动、碎片等“活”类中,尽量将对象的实现放在回调方法中

关于类、生命周期的一些个人理解
类好比一个“袋子”,有的袋子只装了一些工具(方法等);有些袋子(如活动、碎片)里除了工具外,还装了一条具有活力的“串珠”,串珠上每个“珠子”就是一个回调方法,程序按顺序从第一个“珠子”开始执行,直到最后一个珠子,这就是生命周期。生命周期是编程高度“模式化”的体现,可以提高编程质量和速度,若用不好,会起副作用,如本例。

关于攻坚克难的一些想法
1、解决难题最简单、最有效的方法:别停下来。
2、解决困难要讲求原则、方法。
3、艰难险阻不一定都是坏事。困难是向上攀登的阶梯,最好的学习、最深刻的记忆是克服困难,解决问题。勇敢地迎接下一个困难吧!

Fragment has not been attached yet Fragment 套 Fragment相关推荐

  1. Fragment has not been attached yet 解决方法及源码详解

    前言 在使用Fragment的时候,在内存重启的后,很容易出现一些难以预期的bug,下面将继续一边分析源码,一边看看这个bug是怎么产生的. 这个报错的原因,可能和你的情况并不尽然相同.但是你可以通过 ...

  2. Fragment XXXXXX{xxxxxxxxx} not attached to Activity

    Monkey跑出如下异常.导致Settings Crash E AndroidRuntime: at android.app.Fragment.getResources(Fragment.java:8 ...

  3. android 弹出fragment,Android中ViewPager获取当前显示的Fragment

    前言 在项目中,有时会用到在ViewPager中显示同样类型的Fragment,同时这样的Fragment的个数是动态的,但是PagerAdapter没有给我们提供getCurrentFragment ...

  4. Fragment的生命周期同一Activity下不同Fragment之间的通信

    Android开发:碎片Fragment完全解析(2) Fragment的生命周期 和Activity一样,Fragment也有自己的生命周期,理解Fragment的生命周期非常重要,我们通过代码的方 ...

  5. Android Fragment嵌套ViewPager,ViewPager嵌套多个Fragment

    前几天,项目中要实现这么一个功能.就配置了下.其实很简单,首先 需要阅读下我转载的前两篇文章,都是转载的郭神的,写的非常好.我的项目中逢者必用,其实就相当于一个很好的框架来使用,非常方便. 前两篇的项 ...

  6. Fragment实现类似activity onResume()功能,控制fragment可见与不可见

    众所周知,fragment的onResume()和onPause()方法是和activity绑定在一起的,此时fragment的onResume方法并不能确定在fragment切换前后台时会调用,而a ...

  7. Fragment 跳转到指定的Fragment 与 Activity跳转到指定的Fragment 的方法

    Fragment 跳转到指定的Fragment 主要分为2中情况 1 同一个Activity上的Fragment 跳转到指定Fragment 例如MainActivity 上的Fragment 跳转问 ...

  8. android fragment加载布局的方式,Android中Fragment的加载方式与数据通信详解

    Android中Fragment的加载方式与数据通信详解 发布时间:2020-08-22 18:55:57 来源:脚本之家 阅读:155 作者:Joah 一.加载方式 1. 静态加载 1.1 加载步骤 ...

  9. WaveSwipeRefreshLayout实现微信热文精选,微信热文安卓app版,activity中viewpager套fragment

    微信热文安卓app版,微信热文精选. 安卓结合HTML5快速开发app应用,比原生写出来的效果还要好.极大的减小安卓app应用大小. 代码示例(演示apk):http://download.csdn. ...

最新文章

  1. 扫掠两条引导线_NX10 入门图文教程——异形台架(扫掠或者沿引导线扫掠)
  2. 感觉 Data Access Application Block(DAAB) 里也有可能写得不太好的地方
  3. 爬虫之selenium对cookie的处理
  4. Python的学习过程中not enough values to unpack (expected 2, got 1)解决方案
  5. Python 线性回归
  6. C++开发环境搭建_需要学习的内容介绍_写第一个C++程序---C++语言工作笔记008
  7. SpreadJS使用小结
  8. ArcGIS修改默认文件地理数据库
  9. 记录一个小程序 input输入框格式手机号方法
  10. c语言陈湘骥答案,c语言程序设计实验指导答案陈湘骥
  11. 数学建模-层次分析法(AHP)方法回顾
  12. 斯坦福大学公开课 :机器学习课程笔记-[第1集] 机器学习的动机与应用
  13. pyinstaller spec文件详解
  14. python pycharm spider pip docker
  15. 浏览器端可以直接运行Python了
  16. 网站强制跳转到国家反诈中心如何解封
  17. CDMA sid, nid, bid 含义解释
  18. 【互联网品读】京东,真的服了,东哥走火入魔了?全员绩效合同
  19. 纯 CSS3 实现波浪效果
  20. 用proxyee-down快速下载百度网盘大文件

热门文章

  1. JAVA使用POI-TL通过Word模板生成Word文件
  2. 公司某应用服务器被挂挖矿病毒处理流程
  3. 十大开源项目_2014年十大开源项目
  4. 24、新增商铺 - 小程序端开发 - 微擎小程序模块应用开发
  5. 什么是顶级域名?有哪些分类?
  6. python爬取ajax动态内容肯德基门店_新手爬虫.全国KFC门店地址抓取.
  7. 凭什么杀程序员祭天?
  8. 有种速度让你望尘莫及 | 手机QQ及Qzone速度优化实践
  9. 如何制订一个有效的内部规范
  10. 谷粒商城12——购物车模块、消息队列RabbitMQ