一、 介绍
Fragment是Android3.0引入的新API。Fragment代表了Activity的子模块,因此可以把Fragment理解成Activity片段。Fragment拥有自己的生命周期,也可以接受它自己的输入事件。Fragment可以让你的APP在现有基础上性能大幅度提高,并且占用内存降低。通俗的来说,Fragment可以让你的app同时适应手机以及平板屏幕。
二、Fragment的特征
Fragment总是作为Activity界面的组成部分。
Fragment可以调用getActivity()方法获取它所在的Activity,Activity可以调用FragmentManager的findFragmentById()或findFragmentByTag()方法获取Fragment。在Activity运行过程中,可以动态的添加、删除、或者替换Fragment。
通过调用FragmentManager的add()、remove()、replace()方法。- 一个Activity可以同时组合多个Fragment;反过来,一个Fragment也可以被多个Activity复用。
- Fragment可以响应自己的输入事件,并拥有自己的生命周期,但他们的生命周期直接被其所属的Activity的生命周期控制。
- -
三、Fragment的生命周期
1.Fragment必须是依存于Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期,它们存在依赖关系。
2.Fragment生命周期的回调函数
onCreate(Bundle savedStatus):创建Fragment时被回调。该方法只会被调用一次。
onCreateView():每次创建、绘制该Fragment的View组件时回调该方法,Fragment将会显示该方法返回的View组件
onActivityCreated():当Fragment所在的Activity被启动后回调该方法。
onStart():启动Fragment时被回调。
onResume():恢复Fragment时被回调,在onStart()方法后一定会回调onResume()方法。
onPause():暂停Fragment时被回调。
onStop():停止Fragment时被回调。
onDestroyView() :销毁该Fragment所包含的View组件时调用。
onDestroy():销毁Fragment时被回调。该方法只会被调用一次。
onDetach() :将该Fragment从Activity中删除、替换完成时回调该方法,在onDestroy()方法后一定会回调onDetach()方法。该方法只会被调用一次。
3.对比一下Activity的生命周期:
可以看到Fragment比Activity多了几个额外的生命周期回调函数
onAttach(Activity)
当Activity与Fragment发生关联时调用。onCreateView(LayoutInflater,ViewGroup,Bundle);
创建该Fragment的视图。onActivityCreate(bundle);
当Activity的onCreate();方法返回时调用。onDestoryView();
与onCreateView相对应,当改Fragment被移除时调用。onDetach();
与onAttach()相对应,当Fragment与Activity的关联被取消时调用。
四、Fragment的创建
1.静态创建Fragment
在这是使用Fragment最简单的一种方式,把Fragment当成普通的控件,直接写在Activity的布局文件中,用布局文件调用Fragment。
步骤:
1、继承Fragment,重写onCreateView决定Fragment布局。
2、在Activity中声明此Fragment,就当和普通的View一样。
在此展示一个例子(使用一个Fragment用于内容布局)
BookDetailFragment.java文件
在这里我们能够看到,可以在各个Fragment当中进行独立的初始化空间并且处理文本框之类的事件,减轻了Activity的负担,我们在Activity中就没有必要写一大推初始化控件和事件响应的代码了,这样就使我们的代码看上去更加的简洁了,可读性大大提高了。
// 重写onCreateView()方法,该方法返回的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_detail,
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;
}
BookDetailFragment只是加载并显示一份简单的布局文件,这份布局文件通过LinearLayout包含两个文本框。
<?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">
<!-- 定义一个TextView来显示图书标题 -->
<TextView
style="?android:attr/textAppearanceLarge"
android:id="@+id/book_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"/>
<!-- 定义一个TextView来显示图书描述 -->
<TextView
style="?android:attr/textAppearanceMedium"
android:id="@+id/book_desc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"/>
</LinearLayout>
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
2.动态创建Fragment
动态使用fragment是最简单的方式,下面介绍如何动态的添加、更新、以及删除Fragment,接着上面所举的静态创建Fragment的例子中,也包含着动态创建,FrameLayout。
下面就是接着上面那个例子的主Activity以及它的布局文件
布局文件
<?xml version="1.0" encoding="utf-8"?>
<!-- 定义一个水平排列的LinearLayout,并指定使用中等分隔条 -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle">
<!-- 添加一个Fragment -->
<fragment
android:name="org.crazyit.app.BookListFragment"
android:id="@+id/book_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<!-- 添加一个FrameLayout容器 -->
<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。代码如下:
MainActivity.java
public class MainActivity extends Activity implements
BookListFragment.Callbacks
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_book_twopane);
}
@Override
public void onItemSelected(Integer id)
{
Bundle arguments = new Bundle();
arguments.putInt(BookDetailFragment.ITEM_ID, id);
BookDetailFragment fragment = new BookDetailFragment();
fragment.setArguments(arguments);
getFragmentManager().beginTransaction()
.replace(R.id.book_detail_container, fragment)
.commit(); // ①
}
}
可以看到我们使用FragmentManager对Fragment进行了动态的加载,这里使用的是replace()方法。
五、Fragment管理与Fragment事务
1.管理
Activity管理Fragment主要依靠FragmentManager,可以调用FragmentById()获取指定的Fragment,也可以调用popBackStack()方法弹出后台Fragment;也可以调用addToBackStack(null)加入栈或者用addOnBackStackChangeListener监听后台栈的变化。
2.事务
如果是增删替换掉Fragment的话,需要借助FragmentTransaction对象,同时添加Fragment的操作,记得操作完之后在使用commit()方法提交事务。