前言
实践是最好的学习方式,技术也如此。
一、简介
1、是什么
- Fragment 翻译过来为:片段、碎片;
- Fragment 直观印象
- 是一部分内容构成的片段,体现在屏幕上就是一块内容区域;页面区域直接是可以进行切换;整体上是存在于
Activity
上;
- 是一部分内容构成的片段,体现在屏幕上就是一块内容区域;页面区域直接是可以进行切换;整体上是存在于
2、为什么要有 Fragment
- 在
Fragment
之前,通常把一个Activity
作为一个页面; - 随着页面元素的增加以及场景的复杂,单个页面已经不能满足需要,在屏幕上通常要同时展示多个区域,多个页面内容,这些内容的切换通常是整体的;
- 为了让一个
Activity
上承载更多的内容,以及这些内容统一管理,引入了Fragment
; - 相对于
Activity
,Fragment
更加轻量级一些,相当于一个子页面的概念;
3. Fragment 详细解释
- 将一块内容区域封装在一起,统一管理,构成一个
Fragment
; Fragment
是依附在Activity
上而存在的;- 一个
Activity
中可以有个多个Fragment
,各个Fragment
之间可以传递数据、互相切换; Fragment
与Activity
类似,也有生命周期函数(onCreate、onPause、onDestory 等);- 一个 Fragment 从开始到结束的==生命周期==流程(因为
fragment
是依附于Activity
存在的,因此fragment
的生命周期会受到Activity
生命周期的影响);- onAttach -> onCreate -> onCreateView -> onViewCreated -> onActivityCreated -> onStart -> onResume -> onPause ->onStop -> onDestoryView -> onDestroy -> onDetach
-
onCreate()
- 创建
fragment
时调用,此时fragment
的视图还没有创建,是fragment
生命周期开始的地方;在这个阶段,fragment
正在被创建,这个阶段通常用于初始化那些不依赖于fragment
视图的。
- 创建
-
onCreateView()
- 是
fragment
生命周期中专门用于创建和设置fragment
视图的阶段,在这个阶段,开发者通常会- 1)加载布局:通过
LayoutInflater
来加载布局文件,这是设置fragment
视图的首要步骤; - 2)初始化视图组件:找到布局文件中的各个组件(如
TextViews
,Buttons
等),并进行相应的设置或事件绑定 ; - 3)处理逻辑:根据传入的参数或应用的状态,调整视图的显示或初始化特定的数据;
- 1)加载布局:通过
- 是
-
onViewCreated()
- 在视图创建完成后并返回给宿主Activity之后调用 ;
-
onActivityCreated
- 当
fragment
所在的Activity
完成oncreate()
时调用;
- 当
-
onStart
- 当
fragment
变得可见时调用;
- 当
-
onResume
- 当
fragment
可见且能够与用户交互时调用;
- 当
-
onPause
- 用户即将离开
fragment
或fragment
即将被停止时调用;
- 用户即将离开
-
onstop
- 当
fragment
不再可见时调用;
- 当
-
ondestory
- 当
fragment
销毁时调用;
- 当
-
过程
- 调用
newInstance
方法:当通过 newInstance 方法创建一个 Fragment 实例时,实际上是调用了 Fragment 的构造方法并设置了相关的参数;在newInstance 方法内部,通过 setArguments 方法将参数传递给 Fragment 实例。 - 生命周期方法
- 当将创建的 Fragment 实例添加到 FragmentManager 并提交事务时,系统会管理Fragment的生命周期;
- 此时,生命周期方法(例如onCreate、onCreateView等)会被系统自动调用;
- 参数传递:在生命周期方法中,可以通过 getArguments 方法获取通过newInstance 传递的参数。这样设计的好处是,在 Fragment 销毁并重新创建时(例如屏幕旋转),Bundle 中的参数会被保留,不会丢失。
- 调用
二、Fragment 与 Activity 的直观理解
Fragment
需要Activity
作为它的框架去支持,多个Fragment
之间可以进行相互切换,每切换一个Fragment
,当前的Fragment
就会填充到当前Activity
并进行呈现,其它的Fragment
会隐藏或者被移除掉;- 每一个
Fragment
上面还可以有子Fragment
;
三、Fragment 的创建
1、Fragment 的创建方式
-
静态创建
- 1)添加依赖
- 包名(包要导对,和工程相匹配的包);
- 2)使用
xml
代码引入Fragment
(在布局中直接写进去)- 创建一个
Fragment
; - 布局代码中用一个容器承接并绑定
- 类比于 button ,用标签在布局中写好,在 Fragment 中的 Java 代码中进行绑定;
- 标签:
Fragment
、FragmentContainerView
;
- 创建一个
- 步骤总结
- 在入口界面(Activity)-> 通过 button 点击进入承载 fragment 的 Activity,在承载 fragment 的 Activity的布局里面利用 <fragment 标签引入 fragment -> 创建 fragment 的 java 代码,通过在标签中加入 android:name 与 fragment 的 java 代码关联起来(中有实现对应 fragment 的 xml 文件的对应)
- 1)添加依赖
-
动态创建
- 添加依赖;
- 创建一个
Fragment
(Java 代码)和布局; - 布局代码中用一个容器(
<androidx.fragment.app.FragmentContainerView
)承接,但不直接在容器中绑定创建的Fragment
; - 代码中,使用
FragmentManager
、FragmentTranction
添加创建的Fragment
到容器(呈现的Activity
)中;
2、Fragment 的增删替查
1) 替换(常见)
- 替换的应用场景:页面上一般只会存在一个
fragment
,添加一个新的fragment
时,会将当前fragment
隐藏或移除; - 替换包括的两个步骤
- 1)将当前容器上的
Fragment
全部移除; - 2)添加新的
Fragment
;
- 1)将当前容器上的
3、Fragment 的数据传递
1)Activity 向 fragment 传递数据
- 通过方法传递(基本的,通过编程语言的基本性质传递数据,没有涉及到 Android 层面)
-
通过构造方法
-
在承载fragment的Activity中创建 fragment 对象时调用其构造方法传递数据,将成员变量设置为传递的数据;
javaFragment fragment = Fragment.newInstance(0, firstPageApps);
-
-
通过 Public 方法
- 在承载
fragment
的Activity
中创建fragment
对象时调用public
方法将成员变量设置为传递的数据;
- 在承载
-
- 通过 Argument
- 是 android 本身提供的向 fragment 传递数据的方式,可用来一次性传递复杂、大量的数据;
- 通过 public setArguments(Bundle args) 传递数据; Bundle 是一种打包的数据,本质是一个键值对;
- 通过 public Bundle getArguments() 接收数据;
- 通过接口
- 通过接口也是一种基于编程语言自身性质的数据通信方式,与 android 本身无关;
- 本质上可以看作就是个观察者模式,即 两个对象,"被观察者 - 观察者"
- 数据由A传到B,A就是被观察者,B就是观察者,B不必亲自观察(因为B不知道A啥时候数据进行变化啥时候需要往外传递数据),它可以派一个小兵替自己观察,当有了结果之后通知B即可,B对相应的数据变化进行展示即可,这个被派去的小兵就是接口;
2)fragment 向 Activity 传递数据
- 通过 getActivity
- 由于 Activity 是 fragment 的承载者,每个 fragment 都可以通过 getActivity() 方法获得承载它的 Activity 对象,从而可以调用这个 Activity 类中定义的方法, 进而向 Activity 传递数据;
- 通过接口
3)fragment 之间传递数据
- 通过 Activity 中转
- 由于 Activity 是各个 fragment 的承载者,所以可以作为中间桥梁(作为底层的东西)为各个 fragment 传递数据 ;
- 通过 Activty 与 fragment 之间传递数据可以知道,在 fragment 中可以通过 getActivity() 获得 Activity 对象;在 Activity 中可以通过 findFragmentById 或者 findFragmentByTag 找到指定的 Fragment。或者 Fragment 作为 Activity 的成员变量直接使用;
- fragment 之间传递数据
- fragmentA 向 fragmentB 传递数据,fragmentA 可以通过 getActivity() 拿到承载 fragmentB 的 Activity 对象,然后通过调用 findFragmentById 或者 findFragmentByTag 找到 fragmentB,找到后就可以调用 fragmentB 的方法,从而传递数据