文章结构
一、概述
Fragment
是 Android 3.0 中引入的一个控件,主要是为了适应不同尺寸设备的 UI 设计,例如在手机和平板中我们就可以通过使用一套 UI 进行两种布局了,如下图所示:
当然它的作用不止于此,它还被广泛地应用于多页面的情况,通过 Fragment
就可以通过一个 Activity
进行多页面的管理,而不需要一个页面就创建一个 Activity
,这样子可以极大地节约我们内存的开销。
讲完 Fragement
的用途之后,接下来说一下 Fragment
的一些注意事项:
Fragment
无法独立存在,它必须依托在Activity
中才能进行显示和操作。Fragment
拥有独立的生命周期,它的生命周期和Activity
的生命周期非常相似,但它的生命周期是受宿主Activity
的影响的。Fragment
我们可以当作一个迷你的Activity
,但是它本身并不属于Android
四大组件的范畴,所以它不需要在AndroidManifest.xml
中进行注册。
在了解了注意事项后,我们接下来看看 Fragment
的生命周期图。
二、Fragment 的生命周期
Android 官方文档对 Fragment
生命周期的描绘如下所示:
左图的生命周期方法介绍如下:
- onAttach:
Fragment
与Activity
建立关联时调用。 - onCreate:创建
Fragment
时调用。 - onCreateView:加载
Fragment
布局的时候调用。 - onActivityCreated:相关联的
Activity
创建完毕后调用。 - onStart:此时
Fragment
可见,但还位于后台,无法与用户进行交互。 - onResume:此时
Fragment
可见并且可以与用户进行交互了。 - onPause:此时
Fragment
失去焦点。 - onStop:此时
Fragment
处于完全不可见状态,准备停止。 - onDestroyView:销毁
Fragment
的视图的时候调用。 - onDestroy:销毁
Fragment
的时候调用。 - onDetach:
Fragment
与Activity
解除绑定的时候调用。
完整生命周期方法调用顺序如下所示:
1.打开界面:
2.按下 Home 键退回桌面
3.再次回到界面
4.按 Back 键退出
Fragment
是由 Activity
进行管理的,当 Fragment
加入 Activity
后,它们之间关系如下:
1.打开界面:
2.按下 Home 键退回桌面
3.再次回到界面
4.按 Back 键退出
三、Fragment 的加载
Fragment
的加载可分为静态加载和动态加载。
1. 静态加载
在 Activity
的 layout
文件中声明 Fragment
,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.marck.fragmenttest.FragmentTest"/>
</LinearLayout>
在布局中添加 fragment
标签,并在 name
属性上添加我们想要添加的 Fragment
。它的优点是使用简单,缺点却也很明显,就是不够灵活,直接占用了 Activity
的一块区域。
2. 动态加载
动态加载是指通过代码的形式添加 Fragment
,只需要在 Activity
中留一块区域供 Fragment
加载,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/layout_fragment"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
然后在代码中,通过 FragmentManager
、FragmentTransaction
来添加 Fragment
,具体代码如下所示:
fragment = new FragmentTest(); // 待添加的 Fragment
FragmentManager manager = getFragmentManager(); // 通过 getFragmentManager 方法获取 FragmentManager
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.layout, fragment); // 调用 add 方法添加 Fragment
transaction.commit(); // 最后调用 commit 进行提交
步骤如下:
- 通过
getFragmentManager
方法获取FragmentManager
的实例。 - 通过
FragmentManager#beginTransaction
方法获取FragmentTransaction
实例。 - 调用
FragmentTransaction#add
方法添加Fragment
,该方法第一个参数为添加的布局 id,第二个参数就是Fragment
实例。 - 添加完成后一定要调用
FragmentTransaction#commit
提交!
FragmentTransaction
还有如下方法,介绍如下:
- add:每次都会新创建
Fragment
实例 - remove:将指定的
Fragment
实例进行销毁 - show:将已存在的
Fragment
实例展示出来 - hide:将已存在的
Fragment
实例隐藏 - detach:执行这个方法只是销毁了
Fragment
的 UI 部分,但Fragment
还存在 - attach:将销毁了 UI 的
Fragment
的视图进行重绘,还原Fragment
- replace:将旧的
Fragment
实例销毁,并创建新的Fragment
实例,相当于remove + add
的组合
日常使用过程中 add
、 show/hide
应当是使用最多的,add
用于第一次加载 Fragment
实例,然后通过 show/hide
进行相应的显示和隐藏。虽然相比其它方法 show/hide
会占有更多的内存,但是它们能使应用页面之间的切换变得快和流畅,带给用户更好的体验。
四、Fragment 和 Activity 之间的通信
Fragment
和 Activity
之间的通信分为 2 个部分:
1. 在 Activity 中管理 Fragment
要在 Activity
中管理 Fragment
,最重要的就是要获取要管理的 Fragment 的实例,获取方式如下:
FragmentManager manager = getFragmentManager();
FragmentTest fragment = (FragmentTest) manager.findFragmentById(R.layout.fragment_test);
通过 findFragmentById
方法即可获得相应的 Fragment
实例,除此之外还可以通过 findFragmentByTag
方法获得相应实例,调用这个方法的前提是我们在添加 Fragment
时为其设置了 Tag
。
2. 在 Fragment 中调用 Activity 的方法
在 Fragment
中获取 Activity
的实例也是比较简单的,通过 getActivity
方法即可获取宿主 Activity
的实例:
MainActivity activity = (MainActivity) getActivity();
获取得实例后我们就能在 Fragment
中调用 MainActivity
的相关方法了。
3. Fragment 与 Fragment 的通信
这种情况比较少见,如果非要进行 Fragment
之间的通信,可以通过在 Fragment
中先获取宿主 Activity
的实例,然后通过宿主 Activity
再获取另一个 Fragment
的实例,从而实现两个 Fragment
之间的通信。