Fragment详解

Fragment是Android 3.0引入的心API,Fragment代表了Activity的子模块,因此可以吧Fragment理解为Activity片段(Fragment本身就是片段的意思)。Fragment拥有自己的生命周期,也可以接受它自己的输入事件。

一、Fragment概述及其设计初衷

Fragment必须被“嵌入”Activity中使用,虽然Fragment也拥有自己的生命周期,但Fragment的生命周期会受它所在的Activity的生命周期控制。例如,当Activity暂停时,该Activity内的所有Fragment都会暂停;当Activity被销毁时,该Activity内的所有Fragment都会被销毁。只有当该Activity处于活动状态时,程序员才可通过方法独立地操作Fragment。

关于Fragment,可以归纳出如下几个特征。

  • Fragment总是作为Activity界面的组成部分。Fragment可调用getActivity()方法获取它所在的Activity,Activity可调用FragmentManager的findFragmentById()或findFragmentByTag()方法来获取Fragment。
  • 在Activity运行过程中,可调用Fragment的add()、remove()、replace()方法动态地添加、删除或替换Fragment
  • 一个Activity可以同时组合多个Fragment;反过来,一个Fragment也可被多个Activity复用
  • Fragment可以响应自己的输入事件,并拥有自己的生命周期,但它们的生命周期直接被其所属的Activity的生命周期控制

Android 3.0引入Fragment的初衷是为了适应大屏幕的平板电脑,这样可以容纳更多的UI组件,且UI组件之间存在交互关系。Fragment简化了大屏幕UI组件的设计,它不需要开发者管理组件包含关系的复杂变化,开发者适应Fragment对UI组件进行分组、模块化管理,就可以更方便低在运行过程中动态更新Activity的用户界面。

二、创建Fragment

与创建Activity类似,开发者实现Fragment必须继承Fragment基类。
开发者实现Fragment,可以根据需要继承Fragment基类或者它的任意子类。接下来,实现Fragment与实现Activity非常相似,它们都需要实现与Activity类似的回调方法,例如onCreate()、onCreateView()、onStart()、onResume()、onPause()、onStop()等

提示:开发Fragment与开发Activity非常相似,区别只是Activity需要继承Activity或其子类;而开发Fragment需要继承Fragment及其子类。与此同时,只要将原来写在Activity回调方法中的代码“移到”Fragment的回调方法即可。

通常来说,创建Fragment需要实现如下三个方法。

  • onCreate():系统创建Fragment后回调该方法,在代码实现中只初始化想要在Fragment中保持的必要组件,当Fragment被暂停或停止后可以恢复
  • onCreateView():当Fragment绘制界面组件时候会回调该方法。该方法必须返回一个View,改View也就是该Fragment所显示的View。
  • onPause():当用户离开该Fragment时将会回调该方法。

对于大部分Fragment而言,通常都会重写上面这三个方法。实际上开发者可以根据需要重写Fragment的任意回调方法,后面详细介绍Fragment的生命周期及其回调方法。

例如:

    //重写改方法,改方法返回View将作为Fragment显示的最急哦按
    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
    {
        //加载/res/layout/目录下的fragment_book_detail.xml布局文件
        View rootview = inflater.inflate(R.layout.fragment_book_list,container,false);
        if(book != null){
            //让book_title文本框显示book对象的title属性
            (TextView)rootView.findViewById(R.id.book_title)).setText(book.title);
            //让book_desc文本框显示book对象的desc属性
            ((TextView)rootView.findViewById(R.id.book_desc)).setText(book.desc);
        }
        return rootView;
    } 

三、Fragment与Activity通信

为了在Activity中显示Fragment,还必须将Fragment添加到Activity中。奖Fragment添加到Activity中有如下两种方式。

  • 在布局文件中使用 fragment…/>元素添加Fragment,fragment…/>元素的android:name属性指定Fragment的实现类。
  • 在Java代码中通过FragmentTransaction对象的add()方法来添加Fragment。

Activity的getFragmentManager()方法可返回FragmentManager,FragmentManager对象的beginTransaction()方法即可开启并返回FragmentTransaction对象。


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:name="com.test.example.bookfragment"
        android:id="@+id/book_list"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    <FrameLayout
        android:id="@+id/book_detail_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"/>

LinearLayout>

上面布局文字使用fragment../>元素添加了BookListFragment,改Activity的左边将会显示一个ListFragment,右边只是一个FrameLayout容器,该FrameLayout容器将会动态更新其中显示的Fragment。下面是Activity代码。

public class MaiActivity extends Activity implements BookListFragment.Callbacks{
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //加载res/layout目录下的activity_book_twopane.xml布局文件
        setContentView(R.layout.activity_book_twopane);
    }
    //实现Callbacks接口必须实现的方法
    @Override
    public void onItemSelected(Integer id){
        //创建Bundle准备向Fragment传入参数
        Bundle arguments = new Bundle();
        arguments.putInt(BookDetailFragment.ITEM_ID,id);
        //创建BookDetialFragment对象
        BookDetailFragment fragment = new BookDetailFragment();
        //向Fragment传入参数
        fragment.setArguments(arguments);
        //使用fragment替换book_detail_container容器当前显示的Fragment
        getFragmentManager.benginTransaction().replace(R.id.detail.container,fragment).commit();//①
    }
}

上面程序中①号粗体字代码就调用了FragmentTransaction的replace()方法动态更新ID为book_detail_container容器(也就是前面布局文件中的FrameLayout容器)中显示的Fragment。

将Fragment添加到Activity之后,Fragment必须与Activity交互信息,这就需要Fragment能获取它所在的Activity,Activity也能获取它所包含的任意Fragment。可按如下方式进行。

  • Fragment获取它所在的Activity:调用Fragment的getActivity()方法即可返回它所在的Activity。
  • Activity获取它包含的Fragment:调用Activity关联的FragmentManager的findFragmentById(int id)或findFragmentByTag(String Tag)方法即可获取指定的Fragment。

提示:
在界面布局文件中使用 fragment…/>元素添加到Fragment时,可以为 Fragment …>元素指定android:id或者android:tag属性。这两个属性都可以标识该Fragment,接下来Activity通过findFragmentById(int id)或findFragmentByTag(String tag)来获取该Fragment。

除此之外,Fragment与Activity需要相互传递数据,可按如下方式进行。

  • Activity向Fragment传递数据:在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法即可将Bundle数据包交给Fragment。
  • Fragment向Activity传递数据或Activity需要在Fragment运行中实时通信:在Fragment中定义一个内部回调接口,再让包含改Fragment的Activity实现该回调接口,这样Fragment即可调用该回调方法将数据传给Activity。

你可能感兴趣的:(Android,android,android,3.0,fragment)