Fragment 相关知识点
activity_fragment_lifecycle生命周期
Fragment 通信
- 在Fragment 中调用Activity中的方法,getActivity()方法获取所附属的Activity中的方法
- 在Activity中调用Fragment中的方法 采用接口回调的形式
- 在Fragment中调用Fragmetn的方法findFragmentById()
replace add Remove
add 是吧一个Fragment添加到一个容器当中,一般在add的时候为了避免重复创建Fragment节省资源,会配合hide 和 replace使用
replace 在添加fragment到容器之前先移除掉相同id的所有Fragment在进行添加
remove 就是移除fragment 没必要多说
对于Fragment操作都会使用Fm得到一个FragmentTransaction事务对象。在一个Activity+多个Fragment的回退处理,使用hide,show这样同级的用着可以。
但是对于导航栏类似功能,多个功能回退就不好用了,此时可以使用addToBackStck,popBackStack 实现。
多个Fragment :
FragmentStatePagerAdapter 和 FragmentPagerAdapter
选择
当Viewpager中fragment数量多的时候用FragmentStatePagerAdapter,反之则用FragmentPagerAdapter
相同点
两者都会保持当前item(即fragment)和前后的item的状态。
显示当前item的同时,Adapter会提前初始化后一个item,并把当前item的前一个 item保存在内存中。
不同点:
在于fragment 存储、恢复、销毁 的方式不同
对滑动过去的页面是否销毁:
例如:依次从左向右有fragment1,fragment2,fragment3三个页面
FragmentPagerAdapter在滑动到fragment3时,fragment1会依次调用onPause()、onStop()、onDestroyView(),再向左滑动到fragment2时,fragment1会调用onCreateView()、onActivityCreated()、onStart()、onResume()。
结论:FragmentPagerAdapter会保留页面的状态,并不会完全销毁掉。
FragmentStatePagerAdapter在滑动到fragment3时,fragment1会依次调用onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()方法,再向左滑动到fragment2时,fragment1会调用onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()。
结论:FragmentStatePagerAdapter会完全销毁滑动过去的item,当需要初始化的时候,会重新初始化页面。
commit() 与 commitAllowingStateLoss()
Activity 被系统回收(界面已经不存在了),为了能在下次打开的时候恢复原来的样子,我们保存页面所有状态,这个时候再去修改界面是不允许的。为了避免这种异常可以用:
transaction.commit AllowingStateLoss()
与commit()不同的是允许丢失页面的状态和信息
Adapter 与Fragment
FragmentPagerAdapter 一般用于少量界面的ViewPager,划过Fragment会一直保存到内存不销毁。
FragmentStatePageAdapter使用与界面较多的ViewPager,他会保存当前界面,上一个界面和下一个界面,最多保存三个,其他的在destroyItem()方法销毁调用,节省内存。
ViewPager 与 Fragmetn结合使用懒加载问题
Fragment初始化的时候会和网络请求一起执行,这样非常耗性能,最理想方式,只有用胡点开和滑动当前Fragment的时候在进行网络请求操作,因此产生懒加载的说法
ViewPager配合Fragment默认加载前两个,会导致网络丢包和阻塞
在Fragment有一个setUserVisibleHint方法这个方法优于onCreate方法,通过isVisibleToUser 告诉我们是否可见,我们可以在可见的时候加载网络
从log上看setUserVisibleHint 调用早于onCreateView,如果在serUserVisibleHit 实现懒加载注意在view初始化结束,避免空指针。
setUserVisibleHint 什么时候调用
- 当Fragment创建的时候,setUserVisibleHint()传入false
- 当Fragment可见时候,setUserVisibleHit()传入true
- 当Fragment 可见----> 不可见的时候,setUserVisibleHint 被调用,切传入false
Fragment 通信原则:
很重要一个原则
您常常希望 Fragment 之间能够进行通信,以实现某种目的,例如根据用户事件改变内容。所有 Fragment 间的通信通过共享的 ViewModel 或关联的 Activity 来完成。两个 Fragment 不得直接通信。
FragmentManager
Fragment 解耦
通信:接口,网络,eventbus,rxbus,广播,handler
handler缺点:
缺点:
耦合,
无法获取activity返回结果,handler单向通信
内存泄露
广播:
缺点:
1.性能差,延迟(充电,重启,wifi,蓝牙,电话,短信等)单一发射源,多个接收方
2.通信体系重,一个发生,多个接受,广播的数量是有限的
3.传播的数据有限
4.代码冗余
EventBus:
缺点:
1.通过反射,性能打折,效率低
2.代码维护困难
3.数据无法返回,单向传递
接口:
简单,效率高,方便,解耦合
缺点:
代码冗余,每个fragment都必须定义自己的独一无二的接口
解决: 万能接口
1. 定义Function抽象类,实现四种抽象类,有参数有返回值,无参数无返回值,只有参数,只有返回值
2. 定义FunctionManager 作为管理Function接口和容器,提供单例模式对外使用
3. 定义BaseFragment 引用FragmentManager set方法
jetpack 便捷的方式
给我们提供了只要在同一个Activity管理下,ViewModel------ViewModelProviders 提供了共享数据的机制