Android<我所理解的Fragment>

1.Fragment(片段 )是什么

Fragment 表示 Activity 中的行为或用户界面部分。

  • 可以将多个片段组合在一个 Activity 中来构建多窗格 UI,以及在多个 Activity 中重复使用某个片段。
  • 可以将片段视为 Activity 的模块化组成部分,它具有自己的生命周期,能接收自己的输入事件;
  • 可以在 Activity 运行时添加或移除片段(有点像您可以在不同 Activity 中重复使用的“子 Activity”)。

片段必须始终嵌入在 Activity 中,其生命周期直接受宿主 Activity 生命周期的影响。 例如:

  • 当 Activity 暂停时,其中的所有片段也会暂停;
  • 当 Activity 被销毁时,所有片段也会被销毁。 不过,当 Activity 正在运行(处于已恢复生命周期状态)时,可以独立操纵每个片段,如添加或移除它们。
  • 当执行此类片段事务时,也可以将其添加到由 Activity 管理的返回栈 — Activity 中的每个返回栈条目都是一条已发生片段事务的记录。 返回栈让用户可以通过按返回按钮撤消片段事务(后退)。

当将片段作为 Activity 布局的一部分添加时,它存在于 Activity 视图层次结构的某个 ViewGroup 内部,并且片段会定义其自己的视图布局。可以通过在 Activity 的布局文件中声明片段,将其作为 元素插入 Activity 布局中,或者通过将其添加到某个现有 ViewGroup,利用应用代码进行插入。不过,片段并非必须成为 Activity 布局的一部分;还可以将没有自己 UI 的片段用作 Activity 的不可见工作线程。

2、为什么需要Fragment

Android 在 Android 3.0(API 级别 11)中引入了片段,主要是为了给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。
由于平板电脑的屏幕比手机屏幕大得多,因此可用于组合和交换 UI 组件的空间更大。
利用片段实现此类设计时,无需管理对视图层次结构的复杂更改。
通过将 Activity 布局分成片段,可以在运行时修改 Activity 的外观,并在由 Activity 管理的返回栈中保留这些更改。

情景:现在公司要让你开发一个应用,其中有一个要求是这样的你编写的应用要同时能够在手机和平板设备上展现出相同的效果,
例如:用户点击一个标题列表中的一个新闻标题的时候,需要给用户展示这篇文章的内容。

这时候你会怎么解决,将标题放在一个Activity,然后标题对应的内容放在一个Activity么?
想想看,这样做有什么不好。只从用户体验来说,这就给用户带来了不好的体验了。
解决办法:

新闻应用可以使用一个片段在左侧显示文章列表,使用另一个片段在右侧显示文章 — 两个片段并排显示在一个 Activity 中,每个片段都具有自己的一套生命周期回调方法,并各自处理自己的用户输入事件。
而当在手机设备上的时候,可以复用这些已经为平板写好的Fragment,这样代码的复用率就更高了,而且用户体验会更好。如下图所示:

这里写图片描述
也就是说,由于每个片段都会通过各自的生命周期回调来定义其自己的布局和行为,可以将一个片段加入多个 Activity,因此应该采用可复用式设计,避免直接从某个片段直接操纵另一个片段。 这特别重要,因为模块化片段我们可以通过更改片段的组合方式来适应不同的屏幕尺寸。 在设计可同时支持平板电脑和手机的应用时,可以在不同的布局配置中重复使用已经写好的片段,以根据可用的屏幕空间优化用户体验。

3.Fragment的生命周期(activity运行时)

Fragment在宿主activity中运行时候的生命周期示意图如下:
这里写图片描述

管理片段生命周期与管理 Activity 生命周期很相似。和 Activity 一样,片段也以三种状态存在:

继续
片段在运行中的 Activity 中可见。
暂停
另一个 Activity 位于前台并具有焦点,但此片段所在的 Activity 仍然可见(前台 Activity 部分透明,或未覆盖整个屏幕)。
停止
片段不可见。宿主 Activity 已停止,或片段已从 Activity 中移除,但已添加到返回栈。 停止片段仍然处于活动状态(系统会保留所有状态和成员信息)。 不过,它对用户不再可见,如果 Activity 被终止,它也会被终止。

同样与 Activity 一样,假使 Activity 的进程被终止,而需要在重建 Activity 时恢复片段状态,也可以使用 Bundle 保留片段的状态。可以在片段的 onSaveInstanceState() 回调期间保存状态,并可在 onCreate()、onCreateView() 或 onActivityCreated() 期间恢复状态。

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

在其他方面,管理片段生命周期与管理 Activity 生命周期非常相似。 因此,管理 Activity 生命周期的做法同样适用于片段。
Activity 的生命周期对Fragment生命周期的影响:
这里写图片描述

注意:如需 Fragment 内的某个 Context 对象,可以调用 getActivity()。但要注意,请仅在片段附加到 Activity 时调用 getActivity()。如果片段尚未附加,或在其生命周期结束期间分离,则 getActivity() 将返回 null。

片段所在的 Activity 的生命周期会直接影响片段的生命周期,其表现为,Activity 的每次生命周期回调都会引发每个片段的类似回调。 例如,当 Activity 收到 onPause() 时,Activity 中的每个片段也会收到 onPause()。

不过,片段还有几个额外的生命周期回调,用于处理与 Activity 的唯一交互,以执行构建和销毁片段 UI 等操作:

onAttach()
在片段已与 Activity 关联时调用(Activity 传递到此方法内)。
onCreateView()
调用它可创建与片段关联的视图层次结构。
onActivityCreated()
在 Activity 的 onCreate() 方法已返回时调用。
onDestroyView()
在移除与片段关联的视图层次结构时调用。
onDetach()
在取消片段与 Activity 的关联时调用.。

在 Activity 中使用片段的一大优点是,可以根据用户行为通过它们执行添加、移除、替换以及其他操作。 提交给 Activity 的每组更改都称为事务,可以使用 FragmentTransaction 中的 API 来执行一项事务。也可以将每个事务保存到由 Activity 管理的返回栈内,从而让用户能够回退片段更改(类似于回退 Activity)。

如果向事务添加了多个更改(如又一个 add() 或 remove()),并且调用了 addToBackStack(),则在调用 commit() 前应用的所有更改都将作为单一事务添加到返回栈,并且返回按钮会将它们一并撤消。
如果没有在执行移除片段的事务时调用 addToBackStack(),则事务提交时该片段会被销毁,用户将无法回退到该片段。 不过,如果在删除片段时调用了 addToBackStack(),则系统会停止该片段,并在用户回退时将其恢复。
对于每个片段事务,都可以通过在提交前调用 setTransition() 来应用过渡动画。

4.创建对 Activity 的事件回调

在某些情况下,可能需要通过片段与 Activity 共享事件。执行此操作的一个好方法是,在片段内定义一个回调接口,并要求宿主 Activity 实现它。 当 Activity 通过该接口收到回调时,可以根据需要与布局中的其他片段共享这些信息。

例子:一个新闻应用的 Activity 有两个片段 — 一个用于显示文章列表(片段 A),另一个用于显示文章(片段 B)。
片段 A 必须在列表项被选定后告知 Activity,以便它告知片段 B 显示该文章。

在本例中,OnArticleSelectedListener 接口在片段 A 内声明:

public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}

然后,该片段的宿主 Activity 会实现 OnArticleSelectedListener 接口。将来自片段 A 的事件通知片段 B。为确保宿主 Activity 实现此接口,片段 A 的 onAttach() 回调方法(系统在向 Activity 添加片段时调用的方法)会通过转换传递到 onAttach() 中的 Activity 来实例化 OnArticleSelectedListener 的实例:

public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...
}

如果 Activity 未实现接口,则片段会引发 ClassCastException。实现时,mListener 成员会保留对 Activity 的 OnArticleSelectedListener 实现的引用,以便片段 A 可以通过调用 OnArticleSelectedListener 接口定义的方法与 Activity 共享事件。
具体的参考这篇文章:Fragment之间的通信以及Fragment和Activity的通信

5.Fragment中FragmentTransaction 的三种add方法

请看这篇文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值