关于fragment

先上fragment的生命周期:

这里写图片描述

关于activity与fragment生命周期的关系:

这里写图片描述

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

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

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

例如,新闻应用可以使用一个片段在左侧显示文章列表,使用另一个片段在右侧显示文章—两个片段并排显示在一个 Activity 中,每个片段都具有自己的一套生命周期回调方法,并各自处理自己的用户输入事件。 因此,用户不需要使用一个 Activity 来选择文章,然后使用另一个 Activity 来阅读文章,而是可以在同一个 Activity 内选择文章并进行阅读,如图 1 中的平板电脑布局所示。(一个activity管理多个fragment的例子)
这里写图片描述

您应该将每个片段都设计为可重复使用的模块化 Activity 组件。也就是说,由于每个片段都会通过各自的生命周期回调来定义其自己的布局和行为,您可以将一个片段加入多个 Activity,因此,您应该采用可复用式设计,避免直接从某个片段直接操纵另一个片段。 这特别重要,因为模块化片段让您可以通过更改片段的组合方式来适应不同的屏幕尺寸。 在设计可同时支持平板电脑和手机的应用时,您可以在不同的布局配置中重复使用您的片段,以根据可用的屏幕空间优化用户体验。 例如,在手机上,如果不能在同一 Activity 内储存多个片段,可能必须利用单独片段来实现单窗格 UI。

创建片段

onCreate()
系统会在创建片段时调用此方法。您应该在实现内初始化您想在片段暂停或停止后恢复时保留的必需片段组件。
onCreateView()
系统会在片段首次绘制其用户界面时调用此方法。 要想为您的片段绘制 UI,您从此方法中返回的 View 必须是片段布局的根视图。如果片段未提供 UI,您可以返回 null。
onPause()
系统将此方法作为用户离开片段的第一个信号(但并不总是意味着此片段会被销毁)进行调用。 您通常应该在此方法内确认在当前用户会话结束后仍然有效的任何更改(因为用户可能不会返回)。

大多数片段应至少实现这3中方法

添加用户界面

片段通常用作 Activity 用户界面的一部分,将其自己的布局融入 Activity。
为帮助您执行此操作,onCreateView() 提供了一个 LayoutInflater 对象。
传递至 onCreateView() 的 container 参数是您的片段布局将插入到的父 ViewGroup(来自 Activity 的布局)。

public static class ExampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}

inflate() 方法带有三个参数:

1.您想要扩展的布局的资源 ID;
2.将作为扩展布局父项的 ViewGroup。传递 container 对系统向扩展布局的根视图(由其所属的父视图指定)应用布局参数具有重要意义;
3.指示是否应该在扩展期间将扩展布局附加至 ViewGroup(第二个参数)的布尔值。(在本例中,其值为 false,因为系统已经将扩展布局插入 container—传递 true 值会在最终布局中创建一个多余的视图组。

向 Activity 添加片段

通常,片段向宿主 Activity 贡献一部分 UI,作为 Activity 总体视图层次结构的一部分嵌入到 Activity 中。可以通过两种方式向 Activity 布局添加片段:
1.在 Activity 的布局文件内声明片段

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

中的 android:name 属性指定要在布局中实例化的 Fragment 类。当系统创建此 Activity 布局时,会实例化在布局中指定的每个片段,并为每个片段调用 onCreateView() 方法,以检索每个片段的布局。系统会直接插入片段返回的 View 来替代 元素。(也就是说fragment最后就变成了带有独立生命周期和事件处理方式的view嵌入到当前activity中)

每个片段都需要一个唯一的标识符,可以通过三种方式为片段提供 ID:
1.为 android:id 属性提供唯一 ID
2.为 android:tag 属性提供唯一字符串
3.如果您未给以上两个属性提供值,系统会使用容器视图的 ID

2.通过编程方式将片段添加到某个现有 ViewGroup

要想在您的 Activity 中执行片段事务(如添加、删除或替换片段),您必须使用 FragmentTransaction 中的 API。
如添加一个fragment:

android.app.FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
android.app.Fragment fragment = new ExampleFragment();
transaction.add(R.id.content_fragment,fragment);
transaction.commit();

添加没有 UI 的片段:
您还可以使用片段为 Activity 提供后台行为,而不显示额外 UI。要想添加没有 UI 的片段,请使用 add(Fragment, String) 从 Activity 添加片段(为片段提供一个唯一的字符串“标记”,而不是视图 ID)。这会添加片段,但由于它并不与 Activity 布局中的视图关联,因此不会收到对 onCreateView() 的调用。因此,您不需要实现该方法。

您可以使用 FragmentManager 执行的操作包括:

1.通过 findFragmentById()(对于在 Activity 布局中提供 UI 的片段)或 findFragmentByTag()(对于提供或不提供 UI 的片段)获取 Activity 中存在的片段
2.通过 popBackStack()(模拟用户发出的 Back 命令)将片段从返回栈中弹出
3.通过 addOnBackStackChangedListener() 注册一个侦听返回栈变化的侦听器

问题:how to set a fragment`s id programmatically?
答1:
You can’t set a fragment’s ID programmatically.
There is however, a String tag that you can set inside the FragmentTransaction which can be used to uniquely identify a Fragment.
答2:
Turns out you may not need to know the fragment id.

From the docs:

public abstract Fragment findFragmentById (int id)

Finds a fragment that was identified by **the given id either
when inflated from XML**(就是xml中设置的idor as **the container ID when added in
a transaction**.

The important part is “as the container ID when added in a transaction“.

所以:

so:
getSupportFragmentManager()
    .beginTransaction()
    .add(R.id.fragment_holder, new AwesomeFragment())
    .commit();

and then:
AwesomeFragment awesome = (AwesomeFragment)
     getSupportFragmentManager()
          .findFragmentById(R.id.fragment_holder);
//就可以得到指定id的fragment

要想将事务应用到 Activity,您必须调用 commit()。不过,在您调用 commit() 之前,您可能想调用 addToBackStack(),以将事务添加到片段事务返回栈。 该返回栈由 Activity 管理,允许用户通过按“返回” 按钮返回上一片段状态。

如果您要向同一容器添加多个片段,则您添加片段的顺序将决定它们在视图层次结构中的出现顺序

与activity通信

尽管 Fragment 是作为独立于 Activity 的对象实现,并且可在多个 Activity 内使用,但片段的给定实例会直接绑定到包含它的 Activity。

具体地说,片段可以通过 getActivity() 访问 Activity 实例,并轻松地执行在 Activity 布局中查找视图等任务。

创建对 Activity 的事件回调
简单说就是在fragment中创建一个接口,然后令activity实现这个接口,在onAttach(Activity activity)中将activity强制转换为该接口,然后就可以调用接口函数了。
具体:

public static class FragmentA extends ListFragment {
    ...
    //监听器
    OnArticleSelectedListener mListener;
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
        //实例化该接口
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Append the clicked item's row ID with the content provider Uri
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Send the event and Uri to the host activity
        mListener.onArticleSelected(noteUri);
    }
    ...
}

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

当在xml中配置fragment时,程序会立即实例化该fragment,使得该fragment可见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值