第十九个项目——使用Fragment组织UI页面

实验目的

  • 掌握Fragment组件的使用方法;

  • 掌握FragmentActivity组件的交互方式;

实验要求

  • 使用Fragment实现新闻列表加载

实验内容

Fragment中文名为片段碎片,它可视为Activity UI页面中的部分或轻量级的Activity,其具备与Activity相似的生命周期。通过Fragment可将原有的ActivityUI页面进行划分,提升UI页面的可重用性以及适配性。本实验通过Fragment第七个项目中新闻列表页面进行重构,介绍Fragment的基本使用方法。

使用Fragment时,需要从自定义Fragment子类,并至少需要重写下列三个方法:

  • onCreate(),与Activity中的onCreate()方法相似,该方法在创建Fragment实例时被回调,

    通常进行Fragment中组件的初始化;

  • onCreateView(),该方法在当需要Fragment绘制UI时被调用,方法需要返回Fragment的UI布局根视图;

  • onPause(),该方法在用户离开FragmentUI页面时被调用,通常进行数据持久化或组件销毁;

除了上述三个方法必须进行重写外,Fragment还包含了与生命周期相关的其他几个回调函数,详见官方开发文档。

步骤一,打开第七个项目

打开第七个项目,在该项目的基础上完成本次实验。

步骤二,新建NewsListFragment

Project窗口中选择app/java文件夹,右击选择【New】->【Fragment】->【Fragment(Blank)】,在弹出的 New Android Component对话框中Fragment Name文本框中输入NewsListFragment, 勾选Create layout XML?、取消勾选Include fragment factory methods?Include interface callbacks复选框,点击【Finish】完成新建Fragment的创建, 具体如图1. 新建NewsListFragment所示。

图1. 新建NewsListFragment

完成新建操作后,在项目中将生成NewsListFragment.java以及fragment_news_list.xml两个文件,分别对应 Fragment的源文件以及布局文件。

使用Fragment重构第七个项目,主要是将原在MainActivity中各回调函数的业务代码相应的迁移到NewsListFragment相应的回调函数中,而原有activity_main.xml布局元素(除根视图元素外)也可一并迁移至fragment_news_list.xml文件中。

步骤三,更改fragment_news_list.xml布局文件

第七个项目activity_main.xml布局文件中的ListView标签剪切并复制到fragment_news_list.xml文件中,具体代码如下所示。

步骤四,修改NewsListFragment类定义

NewsListFragment中实现新闻列表加载功能,主要思路是将原MainActivity中的业务代码逐一剪切复制到NewsListFragment当中。

1. 将titles、newsAdapter等对象声明复制到NewsListFragment中

titlesnewsListnewsAdapter等对象申明从MainActivity剪切复制到NewsListFragment中。

2. 将initData()方法复制到NewsListFragment中

initData()方法定义从MainActivity剪切复制到NewsListFragment中。

3. 重写NewsListFragment的onCreate()方法

NewsListFragment类中重写onCreate()方法,在其中调用initData()方法进行新闻列表数据初始化。

4. 重写NewsListFragment的onCreateView()方法

onCreateView()方法在Fragment绘制UI时被回调,该方法返回值为完成布局渲染的根视图元素。 为方便加载布局,该方法包含了三个参数:

  • LayoutInflater inflater,用于加载布局的LayoutInflater对象;

  • ViewGroup containerFragment加载的布局应嵌入进的ViewGroup对象;

  • Bundle savedInstanceState,初始化所需的Bundle对象;

NewsListFragmentonCreateView()方法中,首先,通过getActivity()获取到与绑定当前FragmentActivity对象,并将其作为Context上下文对象进行保存,便于后续使用;其次,通过LayoutInflater对象加载了fragment_news_list布局;最后,通过加载好的布局绑定ListView控件对象,并设置该对象所需的NewsAdapter适配器。

完成将MainActivity的代码复制到NewsListFragment后,MainActivity类定义代码如下所示。

步骤五,加载Fragment

Activity中加载Fragment有2种方式:

  • 静态加载,在Activity对应的布局中使用标签进行静态加载;

  • 动态加载,在Activity中使用FragmentManagerFragmentTransaction动态对Fragment进行数据加载及绑定;

本实验中使用静态加载的方式加载Fragment,打开activity_main.xml布局文件,由于在步骤三 中已经将原ListView标签从activity_main.xml中剪切复制到fragment_news_list.xml中,因此直接在 activity_main.xml根视图元素中加入标签,并通过android:name属性指定 所需加载的Fragment类名(包含包名),最终的布局文件代码如下所示。

步骤六,编译并运行项目

编译并运行项目,其执行效果与第七个项目相同。

附:Fragment动态加载

动态加载Fragment需要使用FragmentManagerFragmentTransaction两个组件。动态加载Fragment需要指定对应的ViewGroup视图容器,并通过FragmentTransaction完成事务操作。

1. 首先调整activity_main.xml布局文件

activity_main.xml布局文件中,需要定义ViewGroup视图容器作为动态加载Fragment的根视图容器, 在本实验中,使用ConstraintLayout作为根视图容器,并指定其id属性为fragment_container, 具体代码如下所示。

2. 修改MainActivity的onCreate()方法

Fragment 静态加载方式中,通过在布局文件中指定,当Activity被实例化时, 指定的Fragment将被实例化,且该Fragment对象对应的onCreate()onCreateView()方法会被回调执行。

动态加载Fragment则需要通过FragmentTransaction碎片事务组件完成。 首先,需要获取FragmentManager对象; 其次,调用FragmentManager对象的beginTransaction()方法获得FragmentTransaction对象;在此基础上 调用FragmentTransaction对象的相应方法添加、替换Fragment至指定的ViewGroup视图容器;最后, 调用FragmentTransaction对象的commit()方法提交碎片事务,执行Fragment加载操作。

在该过程中,以下几个方法尤为重要:

  • getSupportFragmentManager(),获取FragmentManager对象;

  • FragmentManager.beginTransaction(),开始碎片事务,获得FragmentTransaction对象;

  • FragmentTransaction.add()FragmentTransaction.replace()

    添加或替换Fragment至指定ViewGroup视图容器;

  • FragmentTransaction.addToBackStack(),添加Fragment至返回栈;

  • FragmentTransaction.commit(),提交碎片事务;

如下代码所示,首先获取了FragmentManager对象,并开始FragmentTransaction碎片事务,再将实例化的NewsListFragment对象通过FragmentTransaction.add()方法添加到R.id.fragment_container视图容器中,最后通过FragmentTransaction.commit()提交碎片事务,完成Fragment动态加载操作。

实验小结

通过本次实验,你应该掌握了如下知识内容:

  • 使用Fragment组织UI界面及逻辑;

  • 使用FragmentManagerFragmentTransaction进行Fragment动态加载;

Last updated

Was this helpful?