fragment的行为和用法都和activity比较相似,它也有自己的生命周期,可以响应接收到的各种事件,值得注意的是一个fragment要总是放入到一个activity中,且activity的生命周期也会影响fragment
下面看一下fragment的生命周期官方文档给出的图:
使fragment能够呈现可见状态(能够与用户交互)的一些列核心生命周期方法有:
onAttach
当fragment和它的activity有关联的时候被调用
onCreate
整个系统创建fragment时调用,用来初始化fragment,相当于activity的onCreate
onCreateView
当第一次创建用户界面的回调方法,返回与fragment相关的视图
onActivityCreated
通知fragment它自己的activity已经完成
onViewStateRestored
告知fragment 其视图层次的所有保存的状态都已经恢复了
onStart
使fragment对用户可见(基于包含它的activity已经启动了)
onResume
使fragment与用户可进行交互(基于包含它的activity已经处于resume状态)
当一个fragment不再被使用的时候,它会经过一系列的反向回调方法:
onPause
fragment不再与用户进行交互,要么由于activity处于暂停态,要么由于在activity中一个fragment的操作正在被修改
onStop
fragment不再与用户可见,要么因为它的activity被停止,要么因为在activity中一个fragment的操作正在被修改
onDestroyView
允许fragment清理它的资源视图
onDestroy
被调用去做fragment状态的最终清理
onDetach
在fragment不再与其activity有关联之前立刻调用
在上述fragment的生命周期中,大多数程序都必须要去实现的是onCreate,onCreateview和onPause三个回调的方法
--------------------------------------------------------------------------------------------------------------------------------------------------------通常我们会继承系统内置的fragment的三个派生类:
DialogFragment
对话框式的Fragments。可以把fragmentdialog并入到到activity的返回栈中,使用户能再返回到这个对话框。
ListFragment
显示一个列表控件,就像ListActivity类,它提供了很多管理列表的方法,onListItemClick和setListAdapter等。
PreferenceFragment
显示一个Preference对象组成的列表,类似PreferenceActivity,主要用来创建设置界面。
Fragment界面添加
了解过fragment的生命周期等简单知识,于是去看官方文档来了解更多相关内容,要添加fragment到我们的UI界面中,给出了两种常用的方法,第一个是在activity的布局xml文件中使用<fragment>标签声明,第二个是在java代码中将fragment添加到一个ViewGroup,我比较习惯于使用第一种XML布局的方式,这里只是介绍了第一种, 在主activity中纵向加入两个fragment,使用<fragment>标签声明,每个fragment有各自的layout布局,都作为activity的一部分
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity"
- android:orientation="vertical"
- android:background="#7ecef4">
- <fragment
- android:name="com.example.fragementexam.FragementList"
- android:id="@+id/frag_list"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="2"/>
- <fragment
- android:name="com.example.fragementexam.FragementDetails"
- android:id="@+id/frag_detail"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="1"/>
- </LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:background="#7ecef4">
<fragment
android:name="com.example.fragementexam.FragementList"
android:id="@+id/frag_list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2"/>
<fragment
android:name="com.example.fragementexam.FragementDetails"
android:id="@+id/frag_detail"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
之后要为每一个fragment添加界面,单独写每个的layout,然后嵌入到activity中,我们必须要在每个Fragment的类中实现onCreateView()方法,并将layout添加进去;如果你的Fragement类本身继承了ListFragment,则不需要必须实现onCreateView(),因为默认已经返回了ListView控件对象
下面是一段Fragment类如何从布局xml文件中生成对象的,主要就是在onCreateView()方法中添加进去布局文件:
- public class FragementDetails extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- return inflater.inflate(R.layout.frag_detail, container,false);
- }
- }
public class FragementDetails extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.frag_detail, container,false);
}
}
其中
inflater用于向fragment中添加view
container用来存放fragment其layout的ViewGroup对象
savedInstanceState类似于onCreate()中相同的Bundle参数,用于恢复状态
inflater的inflate方法的三个参数分别是:
int resource:fragment的layout资源ID。
ViewGroup root:存放fragment的layout的ViewGroup
boolean attachToRoot:是否在创建fragment的layout时,把layout添加到container上面去
Fragment的管理方式
要管理fragment,我们需要用到FragmentManager,在fragement所在的activity中通过getFragment来获得,FragmentManager常用之处;
1使用方法findFragmentById()或findFragmentByTag(),获取activity中已存在的fragment们。
2使用方法popBackStack()从activity的后退栈中弹出fragment们(这可以模拟后退键引发的动作)。
3用方法addOnBackStackChangedListerner()注册一个侦听器以监视后退栈的变化。
----------------------------------------------------------------------------------------------------------------------------------------------------
通过FragmentManager我们还可以来执行对fragment的事务操作,即在同一时刻执行一组动作,首先通过begintransaction获取一个事物的实例,然后可以执行一系列的事务操作,如add(),remove(),replace(),最后使用commint()方法提交事务
下面的代码片段展示了一个简单的事务操作
- public class FragmentPreferences extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- getFragmentManager().beginTransaction()
- .replace(android.R.id.content, new PrefsFragement()).commit();
- }
- public static class PrefsFragement extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.preferences);
- }
- }
- }
public class FragmentPreferences extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new PrefsFragement()).commit();
}
public static class PrefsFragement extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
值得注意的是只能在activity处于可保存的状态时提交事务(比如onPause和onStop方法中),否则会引起异常,这是因为fragment的状态会丢失。如果要在可能丢失状态的情况下提交事务,请使用commitAllowingStateLoss()。