转载请注明:
http://blog.csdn.net/sinat_30276961/article/details/48176761
初步介绍
什么是fragment?fragment可以代表一个行为,或者是一个界面的一部分。你可以在一个activity里使用两个或以上的fragment,并且这些fragment还可以被其他activity使用。
你可以认为fragment是对一个activity的模块化处理。它如同activity一样,有生命周期,可以接收事件,可以被activity动态管理(添加,隐藏,删除等)。
需要指出的是fragment的生存依赖于activity,可以认为activity是fragment的衣食父母。fragment是内嵌在activity里,它的生命周期直接受activity影响。比方说,一个activity处于onPause()了,那么它内部管理的所有fragment都会进入onPause()状态。明显的,activity内部有遍历所有fragment,并调用它们的onXXX()。
也就是说,activity里有维护一个fragment的管理体系,具体是什么呢?
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
它继承自FragmentManager,里面有维护一些list,用来保存激活状态的、新增的、在堆栈里的等等的fragments和FragmentTransaction。
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
static boolean DEBUG = false;
static final String TAG = "FragmentManager";
static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
static final String TARGET_STATE_TAG = "android:target_state";
static final String VIEW_STATE_TAG = "android:view_state";
static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
ArrayList<Runnable> mPendingActions;
Runnable[] mTmpActions;
boolean mExecutingActions;
ArrayList<Fragment> mActive;
ArrayList<Fragment> mAdded;
ArrayList<Integer> mAvailIndices;
ArrayList<BackStackRecord> mBackStack;
ArrayList<Fragment> mCreatedMenus;
我们可以看到,第17行的mBackStack里保存的是BackStackRecord类型,它就是继承自FragmentTransaction。这个保存的就是一些事务,通过FragmentTransaction.addToBackStack()添加进去。
就像是数据库操作一样,fragment操作也是一个事务,你可以把某个事务放入堆栈(就是mBackStack),然后用户点返回时,就会弹出这个事务。
下面代码是Activity的onBackPressed
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
return;
}
if (!mFragments.popBackStackImmediate()) {
finishAfterTransition();
}
}
当堆栈里有事务,mFragments.popBackStackImmediate()就会返回true了,activity就不执行finish了。然后,在popBackStackImmediate,它会把对应fragment所在ui返回到当前弹出的事务执行前的状态。这样,就实现了按返回会回退到先前状态的效果。
当你添加fragment到一个activity时,它是添加到一个viewgroup里。而这个viewgroup就是当前这个activity维护的布局view的一部分。然后,fragment本身维护一个布局view。你可以通过两种方式添加fragment到activity:
1.通过在布局文件里放一个viewgroup容器,用来动态添加、移除fragment。
2.直接使用< fragment >标签。
其实,还有第三种,那就是它不成为activity布局的一部分,只是单纯的用它来做其他事情,类似一个service。
设计哲学
说到fragment,我们总要了解一下它的由来吧。它最初是被用来解决平板ui设计上的麻烦的。我们都知道,手机和平板的屏幕尺寸相差很大,而且,手机一般是竖着用的,而平板一般是横着用的。这样一来,一个应用就要针对这两个情况分别做两套ui,甚至是两套不同的方案。不提开始开发时需要消耗的时间,在维护上更是一大麻烦。
鉴于此,在android3.0开始,google大神们就想出了一个ui碎片化的方案,然后fragment就诞生了。fragment的英文意思就是”碎片化”。它的作用如同它的含义一样,就是把ui分成各个小部分,然后再拼起来,并在使用过程中可以动态的替换。
举个例子说吧,现在我们要做个资讯类的应用。一般在手机端是这样的:第一个界面用来显示一个列表,展示给用户一些资讯的标题和一些关键画面。然后通过点击列表某个item,再进入第二个界面。第二个界面用来显示详细的资讯。
这样的应用我们看到的也很多了。那么问题来了,如果没有fragment,你会怎么去做平板端的ui。以前的方案可能会是这样:针对大屏幕,设计ui,使其左边显示列表,右边显示内容,这些通过一个activity去控制它。针对手机屏幕,只能通过两个activity来做。这样一来,通过各种条件控制这两套方案,还不如直接写两个应用得了。
有了fragment,那么我们就可以这样设计。
针对平板的ui,我们左边还是放列表,右边放内容,但是都是通过fragment。我们可以命名一个为NewsListFragment,另一个为NewsContentFragment。这样一来,碎片就建立起来了。它们分别有自己的生命周期,分别响应事件,维护逻辑。然后activity就可以轻松很多。
最大的好处是,这两个fragment还可以用在手机端的ui。如下图:
所以,用fragment的好处很明显:
1.ui的复用性大大提高。
我们可以把常用的ui模块通过fragment封装起来,然后重复利用。
2.activity的代码量减少,那部分代码到fragment里去了。逻辑更清晰,更方便维护。
3.针对不同屏幕大小的手机,平板,我们可以应对得更轻松自如。
创建fragment
要创建一个fragment,你需要继承Fragment类。然后你会发现它的回调函数和activity很类似。比方说 onCreate(), onStart(), onPause()和onStop()。事实上,如果你想把以前用activity写的应用改成用fragment写,你会发现改起来其实很快,就是把activity在回调函数的代码搬到fragment的回调函数里就行了。
一般来说,你创建一个fragment,需要至少复写如下几个生命周期回调函数:
1.onCreate()
当创建fragment时,系统会调用onCreate()。所以,你可以把一些需要初始化的变量在那里初始化。
2.onCreateView()
当需要第一次画fragment维护的ui碎片时,系统会调用该回调函数。
它需要返回一个view,该view就是fragment维护的ui碎片。当然你可以返回null,如果你只想要这个fragment给你办点ui以外的事情。
3.onPause()
当用户离开该fragment时会调用该回调函数。一般是它的宿主activity进入onPause()。
以上三个是最常用的,当然fragment的生命周期函数还有很多。我们通过一张图来看下吧:
生命周期
通过上面的图可以看到,fragment的生命周期比activity要多些。那么这两者之间的关系又如何呢?
我们再来看张图:
上述这张图清晰的展示了这两者之间的关系。
我整理一下:
onAttach()
当fragment与宿主activity关联时调用。
onCreate()
当fragment被创建时。
onCreateView()
当创建该view时。
onActivityCreated()
到宿主activity已经执行完onCreate()时调用。
onStart(),onResume(),onPause()和onStop()这几个和activity的那几个一样,就不说了。
onDestroyView()
与onCreateView()相对应,当要销毁view时调用。你可以在那里清理资源。
onDestroy()
与onCreate()相对应,当要销毁fragment时调用。
onDetach()
与onAttach()相对应,被宿主activity取消关联。
这里需要指出的是,fragment的生命周期也可以独立改变,一般是在宿主activity处于resumed状态。比方说添加、移除或隐藏fragment。
ok,关于fragment的基础介绍完了。下一篇Android fragment全面深入解析二将会从代码角度深入讲解fragment的一些特性。