一、概述
fragment是一种控制器对象,activity可以委托它完成一些任务。通常这此任务是就管理用户界面。受管理的界面可以是一整屏,也可以是屏幕的一部分。
activity视图含有可提供fragment视图插入的位置,如果有多个fragment要插入,activity也可以提供多个可插入位置。使用fragment可以绕过activity的一些限制规则。
PS:fragment本身不具有在屏幕上显示视图的能力,因此,只有将它的视图放置于activity的视图层级结构中,fragment视图才有显示在屏幕上的能力。
二、Fragment生命周期
Fragment的生命周期类似于activity的生命周期,它具有暂停、停止、运行状态,也拥有可以覆盖的方法,用来在关键节点完成一些任务。需要注意的是,fragment的生命周与activity的生命周期的一个关键区别,在于,fragment的生命周期不是由OS管理,而是托管给activity来管理。OS无人知晓activity用来管理视图fragment。
(此图来自于Android书籍权威指南)
三、托管方式
- 添加fragment到activity布局中,就等同于,将fragment及其视图与activity视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。
- 在activity代码添加fragment,可以灵活管理fragment视图,控制其添加和移除。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:orientation="vertical" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent"> 8 9 <EditText 10 android:id="@+id/crime_title" 11 android:layout_width="match_parent" 12 android:layout_height="wrap_content" 13 android:hint="@string/crime_title_hint"/> 14 15 </LinearLayout>
四、实现fragment生命周期方法
1 public class CrimeFragment extends Fragment 2 { 3 private Crime mCrime; 4 private EditText mEditText; 5 6 @Override 7 public void onCreate(Bundle savedInstanceState) 8 { 9 super.onCreate(savedInstanceState); 10 mCrime = new Crime(); 11 } 12 13 @Override 14 public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) 15 { 16 View v = inflater.inflate(R.layout.fragment_crime, parent, false); 17 18 mEditText = (EditText)v.findViewById(R.id.crime_title); 19 mEditText.addTextChangedListener(new TextWatcher() 20 { 21 @Override 22 public void beforeTextChanged(CharSequence s, int start, int count, int after) 23 { 24 mCrime.setmTitle(s.toString()); 25 } 26 27 @Override 28 public void onTextChanged(CharSequence s, int start, int before, int count) 29 { 30 31 } 32 33 @Override 34 public void afterTextChanged(Editable s) 35 { 36 37 } 38 }); 39 40 return v; 41 } 42 }
以上代码中,需要注意以下几点:
- 在Fragment类中,onCreate(...)方法的访问权限是公共的(public),而在activity类中,onCreate(...)方法访问权限是被保护的(protected)。
- 类似于activity,fragment同样具有存储及获取状态的Bundle。
- 在fragment中onCreate(...)方法中,没有生成fragment视图。而是配置了fragment实例,但创建fragment视图是通过onCreateView(...)方法实现的,如下:
1 public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){}
通过该方法生成fragment的视图,然后,将生成的View视图返回给activity。
五、FragmentManager
fragmentManager类负责管理fragment,并将它们的视图添加到activity的视图层级结构中。
具体管理的事务:
- 管理fragment队列。
- 管理fragment事务的回退栈。
在activity子类中,添加fragmentManager,用于管理fragment视图。
1 public class CrimeActivity extends FragmentActivity 2 { 3 @Override 4 protected void onCreate(Bundle savedInstanceState) 5 { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_crime); 8 9 // 获取fragmentmanager对象,fragment的队列 10 FragmentManager fm = getFragmentManager(); 11 // 通过资源ID,在fragment队列中,获取到指定的fragment对象 12 Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); 13 if (null == fragment) 14 { 15 // 如未获取到fragment对象,则创建对象并添加到fragment队列中 16 fragment = new CrimeFragment(); 17 fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit(); 18 } 19 } 20 }
以上代码需要注意的是以下几点:
- FragmentManager类是管理fragment视图的队列。
容器资源ID主要作用:
- 告知FragmentManager,fragment视图显示在activity视图中的什么位置。
- R.id是fragment视图在FragmentManager队列中的唯一标识。
六、回顾FragmentManager与Fragment生命周期
在activity处于停止、暂停或运行状态下时,添加fragment会发生什么?
- activity处于停止或暂停状态时,FragmentManager立即驱使fragment快速跟上activity的步伐,直到与activity的最新状态同步。
- activity处于运行状态时,fragment的生命周期会依次调用:
- onAttach(Activity)
- onCreate(Bundle)
- onCreateView(...)
- onActivityCreate(...)
- onStart()
- onResume()
PS:fragment状态与activity状态时时刻刻在保持一致,即使不一致,也是在去保持一致状态的路上。