Android 基础 — 5、碎片Fragment (二) 碎片的动态注册 | 青训营笔记

179 阅读3分钟

这是我参与「第四届青训营」笔记创作的第 13 天

此篇笔记是 Android 基础 —— 5、碎片Fragment (二) 碎片的动态注册

本篇笔记分为 2 部分

  1. 碎片的动态注册
  2. 碎片在动态注册时的生命周期

五、Fragment

本篇笔记将介绍 Fragment 碎片的概念及其用法

包括:通过静态注册方式使用碎片、通过动态注册方式使用碎片(需要配合碎片适配器 FragmentPagerAdapter ),并分析两种注册方式的碎片生命周期,最后结合实战演示了如何使用碎片改进启动引导页。

碎片在动态注册时的生命周期

另外,介绍一下碎片在静态注册时的生命周期,像活动的基本生命周期方法 onCreateonStartonResumeonPauseonStoponDestroy ,碎片同样也有,而且还多出了下面5个生命周期方法。

  • onAttach :与活动页面结合。
  • onCreateView :创建碎片视图。
  • onActivityCreated :在活动页面创建完毕后调用。
  • onDestroyView :回收碎片视图。
  • onDetach :与活动页面分离。

至于这些周期方法的先后调用顺序,观察日志最简单明了。下面是打开活动页面时的日志信息,此时碎片的 onCreate 方法先于活动的 onCreate 方法,而碎片的 onStartonResume 均在活动的同名方法之后。

12:26:11.506:D/StaticFragment:onAttach 
12:26:11.506:D/StaticFragment:onCreate 
12:26:11.530:D/StaticFragment:onCreateView 
12:26:11.530:D/FragmentStaticActivity:onCreate 
12:26:11.530:D/StaticFragment:onActivityCreated 
12:26:11.530:D/FragmentStaticActivity:onStart 
12:26:11.530:D/StaticFragment:onStart 
12:26:11.530:D/FragmentStaticActivity:onResume 
12:26:11.530:D/StaticFragment:onResume

下面是退出活动页面时的日志信息,此时碎片的 onPauseonStoponDestroy 都在活动的同名方法之前。

12:26:36.586:D/StaticFragment:onPause 
12:26:36.586:D/FragmentStaticActivity:onPause 
12:26:36.990:D/StaticFragment:onStop 
12:26:36.990:D/FragmentStaticActivity:onStop 
12:26:36.990:D/StaticFragment:onDestroyView 
12:26:36.990:D/StaticFragment:onDestroy 
12:26:36.990:D/StaticFragment:onDetach 
12:26:36.990:D/FragmentStaticActivity:onDestroy

碎片的动态注册

碎片 Fragment 是个特别的存在,它有点像报纸上的专栏,看起来只占据页面的一小块区域,但是这一区域有自己的生命周期,可以自行其是,仿佛独立王国;并且该区域只占据空间不扰乱业务,添加之后不影响宿主页面的其他区域,去除之后也不影响宿主页面的其他区域。

每个碎片都有对应的 XML 布局文件,依据其使用方式可分为静态注册与动态注册两类。

静态注册指的是在 XML 文件中直接放置 fragment 节点,类似于一个普通控件,可被多个布局文件同时引用。静态注册一般用于某个通用的页面部件(如 Logo 条、广告条等),每个活动页面均可直接引用该部件。

下面是碎片页对应的 XML 文件内容,看起来跟列表项与网格项的布局文件差不多。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#bbffbb"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_adv"
        android:layout_width="0dp"
        android:layout_height="60dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="广告图片"
        android:textColor="#000000"
        android:textSize="17sp" />

    <ImageView
        android:id="@+id/iv_adv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:scaleType="fitCenter"
        android:src="@drawable/test" />
    
</LinearLayout>

下面是与上述 XML 布局对应的碎片代码,除了继承自 Fragment 与入口方法 onCreateView 两点,其他地方类似活动页面代码。

public class StaticFragment extends Fragment {

    private static final String TAG = "jzh";

    // 把碎片贴到页面上
    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        Log.d(TAG, "Fragment onAttach");
    }

    // 页面创建
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Fragment onCreate");
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "Fragment onCreateView");
        return inflater.inflate(R.layout.fragment_static, container, false);
    }

若想在活动页面的 XML 文件中引用上面定义的 StaticFragment ,可以直接添加一个 fragment 节点,但需注意下列两点:

  1. fragment 节点必须指定 id 属性,否则 App 运行会报错。
  2. fragment 节点必须通过name属性指定碎片类的完整路径。

下面是在布局文件中引用碎片的 XML 例子。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:id="@+id/fragment_static"
        android:name="com.example.myadvancedcontrols.fragment.StaticFragment"
        android:layout_width="match_parent"
        android:layout_height="60dp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这里是每个页面的具体内容"
        android:textColor="#000000"
        android:textSize="17sp" />

</LinearLayout>

运行测试 App ,可见此时碎片区域仿佛一个视图,其内部控件同样可以接收点击事件。