Fragment
概念
是一种可以嵌入到activity里面的UI片段,它可以让程序更加合理的利用大屏幕的空间。
为什么要用Fragment
o适配不同的设备
根据大小不同的设备去加载大小不同的布局,例如平板加载一套布局,手机加载一套布局;
o减轻Activity的压力
Activity作为视图的承接和管理在很多场景下过于繁重,需要一个简化的视图管理器来替代Activity的操作。
o代码复用
特别适用于模块化的开发,因为一个Fragment可以被多个Activity嵌套,有个共同的业务模块就可以复用了,是模块化UI的良好组件
其它特点
o可控性
Fragment可以像普通对象那样自由的创建和控制,传递参数更加容易和方便,也不用处理系统相关的事情,显示方式,替换,不管是整体还是部分,都可以做到相应的更改。
oFragment是view controllers,它包含可测试的,解耦的业务逻辑块,由于Fragments是建立在Views的基础上的,Views很容易实现动画效果,因此Fragment在屏幕切换的时候有更好的控制。
生命周期
onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestoryView->onDstory->onDetach
oonAttach:Fragment和Activity相关联时调用;
在这个阶段,可以传入初始化参数;
可以将参数content转换成activity保存下来,避免后期频繁的获取activity
为什么在这个阶段传?
一般情况,都会通过Fragement传初始化参数,但是这样导致的问题就是Fragment重建时,初始化参数就会丢失;如果不想丢失初始化参数,那么就要把初始化参数用setArgument()注入,这样重建的时候就可以在Argument里面取参数;
oonCreate
Fragment被创建时调用
oonCreateView
创建fragment的布局
oonActivityCreate
当activity完成onCreate的时候调用
oonStart
当Fragment可见时调用
oonResume
当Fragment在前台的时候调用
oonPause
当Fragment不在前台的时候调用
oonStop
当Fragment不可见的时候调用
oonDestoryView
当Fragment的UI被从视图结构中移除的时候调用,
当使用repalce()的时候,只会走到当前状态,不会继续走到onDestory,因为在销毁视图的同时,Fragment的状态得以保留,方便下次加载的时候直接走onCreateView,比冷加载快。
oonDestory
销毁Fragment的时候调用
oonDetach
Fragment和Activity解除关联的时候调用。
一些情况下周期变化
创建Fragment
onAttach->onCteate->onCreateView->OnActivityCreate->onStart->onResume
按下home键回到桌面/锁屏
onPause->onStop
从桌面回到Fragment/解锁
onStart->onResume
切换到其它Fragment
默认情况:
不通过FragmentTransaction.addToBackStack(String name)将当前事务添加到返回栈
onPause->onStop->OnDestoryView->onDestory->onDeatch
也就是说,通过replace方法替换Fragment后,原有的Fragment直接销毁。
将当前事务添加到返回栈:
onPause->onStop->onDestoryView
切换到本身的Fragment
默认情况:
onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResum
将当前事务添加到返回栈:
onCreateView->onCreate->onStart->onResum (不确定)
按下Back键退出
onPause->onStop->onDestoryView->onDestory->onDetach()
Activity和Fragment之间进行通信
oFragment可以通过getActivity()得到当前绑定的activity实例,然后进行操作;
o如果Activity里面有Fragment的实例可以直接使用;
o如果没有Fragment实例,可以根据id拿到实例(通过FragmentManager的findFragmentById(int Id)来获取Fragment);
o文件
oHandler
在Fragment里面创建一个Handler实现类,然后在attach()中将这个Handler对象传递给Activity,Activity再通过这个Handler传递消息就可以实现activity->fragment的单向通行;
要是想实现fragment->activity的通信,就通过getActivity()获得activity对象,这样就可以获得activity里面的handler,这样Fragment就可以向Activity发送消息了。
oattach回调
oeventBus
o共享ViewModel,观察其中的LiveData;
o广播
Activity传递数据给Fragment
在创建Fragment实例和Bundle对象并且向Bundle里面添加需要传递的参数之后,就可以通过Fragment.setArguments(Bundle args)将Bundle对象传入Fragment,在Fragment的onCreate()里面通过getArgument()获取这个Bundle对象并从中取出参数。
为什么视图里面建议使用Fragment而不是activity(Fragment相比于activity的优点)
oFragment可以被混淆,而activity不行
Android里面我们一般使用ProGuard进行代码混淆,但是ProGuard是JAVA的混淆器,他不能混淆xml文件,这样就会导致如果activity被混淆,那么manifest就会因为找不到activity文件而导致程序崩溃;四大组件里面其它三个也类似,view也类似(在layout文件中指定的文件包名);
oFragment不是组件,占用资源少;
o切换速度比activity快很多;
add和replace的区别
oadd是直接将新的fragment添加在旧的fragment上,所以一般都会搭配hide()和show()使用;
oreplace()是直接将新的fragment替换旧的fragment,这样能保证有一个fragment,减少了界面的层级,说白了也就是add和remove;
o如果是通过show和hide(),fragment的onpause()和onstop()不会调用,而是调用onHiddenChanged;
Fragment的重建
关于Fragment的重建不需要我们进行任何操作,因为Activity的重建机制会自动帮我们重建Fragment,唯一需要注意的是,Fragment的初始化参数最好写在Argument中。
碎片的简单使用
o静态使用
静态使用就是在layout布局文件中写入fragment(class字段),然后再代码中新建一个类继承自Fragment,重写onCreateView,在onCreateView里面通过inflate绑定layout,然后就可以在activity里面像使用一般的view那样使用了。
o动态使用
动态就是说在layout文件中创建多个Fragment的对象,同时和静态使用一样,创建类继承自Fragment,然后重写onCreateView绑定layout。然后就可以在activity中常见FragmentManager对象以及FragmentTransaction对象,这样就可以通过调用FragmentTransaction中的方法实现动态的使用fragment。transaction中有很多方法,比方说add往当前activity中添加fragment,remove是移除fragment,replace是替换fragment等等。
懒加载
数据要等到页面对用户可见时才进行加载
ViewPager+TabLayout+Fragment
setUserVisibleHint的调用时机总是在初始化时调用,可见时调用,由可见转换成不可见时调用。
FragmentManager+FragmentTranscation+Fragment
https://juejin.cn/post/6844903889318199309