Android笔记—Fragments


资料来源如下

  • 第一行代码(第二版)
  • Android官方文档之App Components(Fragments)

编程环境

  • Android Studio 2.2.3

导语

  • Fragments的艺术之旅

Fragments简介

  • Fragment—片段 是Android 在 Android 3.0(API 11 级)中引入了,主要是为了给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。
  • 可以将多个片段组合在一个 Activity 中来构建多窗格 UI,以及在多个 Activity 中重复使用某个片段。可以将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件,可以在 Activity 运行时添加或删除片段(类似于不同 Activity 中重复使用的“子 Activity”)
  • Google官方文档(中文)

创建Fragments

  • fragment创建过程与Activity类似。
  • 创建Fragment,需要继承一个Fragment类,并实现Fragment的生命周期回调方法,如onCreate(), onStart(), onPause(), onStop()等
  • 一般来说,在Fragment中应至少重写以下这些生命周期方法
    必须重写的时onCreateView()方法.
    • onCreate():创建Fragment实例时,系统回调的方法。在该方法中,对一些必要的组件进行初始化
    • onCreateView():Fragment上绘制UI时,回掉该方法。返回一个View对象,表示Fragment的根视图;若Fragment不需要绑定示图,可以返回null
    • onPause():当用户离开Fragment时回调。在该方法中,对Fragment的数据信息做持久化的保存工作

创建一个Fragment类

  • 新建first_fragme 继承自Fragment

  • Android Studio中 对应Fragment 包有两个,选择support-v4 _(这个版本可以再Android版本中保持Fragment特性一致)

  • Fragment并非一定要绑定一个布局文件,下面会提到。

    1
    2
    3
    4
    5
    6
    7
    public class FirstFragment extends Fragment {
    @Override
    public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState){
    View view = inflater.inflate(R.layout.fragment_firest,container,false);
    return view;
    }
    }
  • 与此对应的fragment_firest布局文件 _
    LinearLayout加一个Button,背景颜色设置为了靛蓝色。

  • onCreateView()方法

    • ViewGroup来自宿主Activity容器布局,Fragment的布局将其作为根视图插入至该视图中。
    • Bundle用于回传之前占据该位置的Fragment实例所保存的Bundle信息,当该Fragment的新实例处于resume状态时,该参数被回传
  • inflate() 方法

    • 参数1(int):需要绑定的Layout的资源ID;

    • 参数2(ViewGroup):绑定的Layout布局的父视图;

    • 参数3(boolean):是否需要将参数1的Layout资源依附于,参数2的ViewGroup上,false,表示不依附。(系统已经默认将Layout插入至ViewGroup中,若为true,将添加一层冗余的视图

在XML将fragment添加到activity

  • 在activity_main.xml中添加如下代码。跟添加一个layout没有太大区别。

    1
    2
    3
    4
    5
    6
    <fragment
    android:id="@+id/left_fragment"
    android:name="ljy.com.fragmenttest.fragment_firest"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"/>
  • 至此一个fragment添加完毕。为了对比,再新建一个second_fragment,背景颜色不同,两者同时添加进activity_main中。

  • Screenshot_1476109113.png

  • 一般来说必须为fragment设定唯一的身份标识,以便当宿主Activity为restart状态时可以恢复fragment

    • android:id属性为fragment指定唯一ID
    • android:tag属性为fragment指定唯一字符串标识
    • 未指定,则该fragment的标识为其父容器控件的ID

动态添加碎片


  • 处理片段时,请谨记:Activity 布局必须包含一个可以插入片段的容器 View

  • 添加或移除片段必须使用 FragmentManager 创建 FragmentTransaction, FragmentTransaction将提供添加、移除、替换片段以及执行其他片段事务所需的 API。Activity 内调用 getSupportFragmentManager() 以获取 FragmentManager

    1
    2
    rightfragment right = new rightfragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
  • 调用 beginTransaction() 创建一个 FragmentTransaction事务,并调用 add() 添加一个片段,做好更改准备时,调用 commit()

    1
    2
    3
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.right_layout,right);
    transaction.commit();
  • 示例:

    • 首先改造一下activity_main.xml_
      FrameLayout包含一个left_fragment

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
        <FrameLayout
      android:id="@+id/right_layout"
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="1">

      <fragment
      android:id="@+id/left_fragment"
      android:name="com.example.fragment_text.leftfragment"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      />
      </FrameLayout>
    • 在MainActivity的onCreate方法中添加fragment

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      //新建准备替换的Fragment实例
      rightfragment right = new rightfragment();

      //新建FragmentManager
      FragmentManager fragmentManager = getSupportFragmentManager();
      // 调用beginTransaction() 创建FragmentTransaction
      FragmentTransaction transaction = fragmentManager.beginTransaction();

      //FragmentTransaction内处理添加/替换等。
      transaction.replace(R.id.right_layout,right);

      //最后执行commit()方法
      transaction.commit();

      管理Fragments/执行Fragment事务

  • Activity中管理Fragment,使用FragmentManager(

    1
    FragmentManager fragmentManager = getFragmentManager();

    可以实现的操作

    • findFragmentById()方法获取由Activity管辖的绑定了UI的Fragment实例
    • popBackStack()方法将Fragment从后退栈中弹出
    • addOnBackStackChangedListener()方法注册监听器,用于监听后退栈的变化
  • Fragment可实现动态添加、删除、替换 等 操作,每一组向Activity提交的变化称为事务,使用FragmentTransaction这操作事务,调用beginTransaction()开启一个事务

    1
    2
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    可实现对Feagment的操作

    • add() //添加
    • remove() //移除
    • replace() //替换
  • 事务要在Activity中生效,调用commit()方法提交

  • commit()方法之前,调用addToBackStack()方法,可以将该事物添加到由Activity管辖的Fragment返回栈中。点击Back键即撤销该事物提交的更改


  • 使用FragmentTransaction操作事务时注意

    • commit()必须在最后调用
    • 一个布局容器中添加多个Fragment,加入的顺序决定了这些Fragment绑定的UI视图在View树中的层级顺序
  • commit()方法提交后,并不会立即执行事务,UI更新只能在主线程中进行,主线程空闲时,才会执行事务操作
    Android也提供了 在UI线程中调用executePendingTransactions()方法,使commit()方法调用后立即执行提交的事务(一般用不到)


与 Activity 通信

  • Fragment 中获取 Activity 实例
    getActivity()方法可以获取到 Activity 实例
    1
    MainActivity activity = (MainActivity) getActivity();
    调用Activity中的试图也很简单,使用findViewById()即可,getActivity()方法返回的既是一个Context对象
    1
    View listView = getActivity().findViewById(R.id.list);

  • 在Fragment中使用Context对象,getActivity()方法,只能是在fragment已经依附于Activity后才能调用。当fragment未依附于某个Activity、或fragment已经处于其生命周期的末尾而不再依附于某个Activity时,调用getActivity()方法会直接返回null

  • Activity 中获取 Fragment 实例()
    FragmentManger提供了findFragmentById()方法

    1
    RightFragment fragment = (RightFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

    如果使用的使support-V4包,则 getFragmentManager()改为getSupportFragmentManager(),代码如下:

    1
    RightFragment fragment = (RightFragment)getSupportFragmentManager().findFragmentById(R.id.example_fragment);
  • Fragment与Frangment之间也可以通过宿主Activity,获取到另一个Fragment实例,调用另一个Fragment中的方法

为Activity创建事件回调

  • 占坑,

Frangment的生命周期

  • 与Activity极为相似,且 Frangment的生命周期与宿主Activity有很大关联

  • 有3种状态

    • Resumed继续:宿主Activity处于running,Fragment处于可见状态
    • Paused暂停:另一个Activity处于前台并获得了焦点,该Fragment的宿主Activity并未被全部遮挡
    • Stopped停止:Fragment不可见或Fragment已被Activity移除,宿主Activity被回收时,Fragment也将被回收
  • fragment_lifecycle.png

宿主Activity的影响

  • activity_fragment_lifecycle.png

重要回调方法

  • onAttach():fragment关联Activity时回调
  • onCreateView():fragment绑定UI视图(加载布局)时回调
  • onActivityCreated():宿主Activity创建完毕 (宿主Activity的onCreate()方法返回) 后调用
  • onDestroyView():与fragment绑定的UI视图被移除时回调
  • onDetach():fragment不再依附于Activity时回调

  • Activity 与Fragment在生命周期之间的最显著差异在于它们在其各自返回栈中的存储方式。
    默认情况下,Activity 停止时会被放入由系统管理的 Activity 返回栈(以便用户通过返回按钮回退到 Activity),
    Frament仅当您在移除片段的事务执行期间通过调用 addToBackStack() 请求保存实例时,系统才会将Fragment放入由宿主 Activity 管理的返回栈。

  • 一旦Activity处于resume状态时,可以自由地添加或移除fragment,也就是说,只有当Activity的状态为resume时,fragment才能够自由地控制自己的生命周期