1.Fragment概要python
学习Fragment的时候能够联系以前学习过的Activity,由于它们有不少类似点:均可包含布局,有本身的生命周期,Fragment可看似迷你活动。正如Fragment的名字--碎片,它的出现是为了解决Android碎片化 ,它可做为Activity界面的组成部分,可在Activity运行中实现动态地加入、移除和交换。一个Activity中可同时出现多个Fragment,一个Fragment也可在多个Activity中使用。活动和碎片像极了夫妻, 虽然紧密联系可是又有独立空间,在一块儿让彼此变得更好。android
下面这个很是经典的例子更直观地说明了Fragment做用:app
2.Fragment生命周期布局
先来看官方文档提供的有关Fragment生命周期的图片。post
是否是能发现Fragment和Activity的生命周期太类似了,如今只须要再介绍几个Activity中没讲过的新方法:学习
onAttach():当Fragment和Activity创建关联时调用spa
onCreateView():当Fragment建立视图时调用操作系统
onActivityCreated():当与Fragment相关联的Activity完成onCreate()以后调用设计
onDestroyView():在Fragment中的布局被移除时调用3d
onDetach():当Fragment和Activity解除关联时调用
在上图中画了几条线,能够看到Fragment周期中的状态几乎都是成对出现的,因此不难理解下图几种变化下Fragment生命周期方法的调用顺序了。
加载到Activity中的Fragment在各类变化下方法的调用顺序更值得注意。须要提一句的是,Activity的FragmentManager负责调用队列中Fragment的生命周期方法,只要Fragment的状态与Activity的状态保持了同步,托管Activity的FragmentManager便会继续调用其余生命周期方法以继续保持Fragment与Activity的状态一致。
Fragment生命周期与Activity生命周期的一个关键区别就在于,Fragment的生命周期方法是由托管Activity而不是操做系统调用的。Activity中生命周期方法都是protected,而Fragment都是public,也能印证了这一点,由于Activity须要调用Fragment那些方法并管理它。
3.加载Fragment方法
如今就来学习如何在Activity中加载Fragment。
(1)静态加载:在托管Activity的layout文件中声明Fragment
静态加载Fragment大体过程如图,分红四步:
下面经过一个简单的例子感觉Fragment静态加载到Activity的过程。
第一步:新建frag_layout.xml,为Fragment指定一个布局,这里简单的放一个TextView和一个Button。
第二步:新建一个MyFragment类并继承Fragment,这里引用android.app包下的就能够,另外一个包下主要用于兼容低版本的安卓系统。而后重写 onCreateView() 方法,这个方法里经过LayoutInflater的inflate()方法将刚刚定义的frag_layout布局加载进来并获得一个View,再return这个View。
第三步:新建mian.xml,做为Activity的布局,使用< fragment>标签添加碎片,而且必定要有android:name属性且值为被加载的Fragment类的包名.类名完整形式。
第四步:在MainActivity中加载main布局。如今MyFragment就完成了静态加载到MainActivity中,这时碎片里的控件天然也是活动的一个部分,可直接在活动中获取到Button的实例,来注册点击事件了。
运行一下看看能不能达到效果:
(2)动态加载:在托管Activity经过代码动态添加
动态加载的代码也很是简单,直接看例子。修改main.xml,将整个< fragment>删掉。但还保留一个LinerLayout的空间而且还给了Id,为什么这样作?立刻揭秘。
接下来在MainActivity中添加几行代码:
可将整个过程大体分为三个步骤:
第一步,先用 getFragmentManager() 方法获取一个FragmentManager对象,再经过它的 beginTransaction() 获取一个FragmentTransaction的实例。
第二步,用beginTransaction. add() 方法将MyFragemnt实例添加到main布局里LinearLayout里,终于知道以前铺垫的Id是怎么回事了。必定要注意,add()方法里的第一个参数是容器视图资源Id,而不是layout。容器视图资源Id有两个做用:告知FragmentManager,碎片视图应该出如今活动视图的什么地方;它也是FragmentManager队列中碎片的惟一标识符。而静态加载时碎片的惟一标识符正是在活动布局里< fragment>下的id。
第三步:调用beginTransaction. commit() 提交。另外,若是容许用户经过按下返回按键返回到前一个Fragment状态,在调用commit()以前先调用 addToBackStack(true) 方法。
这里注意到动态加载进来的Fragment里的控件并不能直接在活动中findViewById获得,那么如何实现点击效果呢,学完下一个知识点就有办法了。
4.Fragment与Activity之间通讯
在活动中能够经过调用 FragmentManager 的 findFragmentById() 方法来获得相应碎片的实例,继而能够调用碎片里的方法。以上面demo举例,若是想获得静态加载碎片的实例,可在MainActivity添加代码以下:
MyFragment myFragment = (MyFragment)getFragmentManager(). findFragmentById(R.id.fragment);
复制代码
若是想获得动态加载碎片的实例,代码以下:
MyFragment myFragment = (MyFragment)fragmentManager(). findFragmentById(R.id.layout);
复制代码
在碎片中也能够经过调用getActivity()方法来获得和当前碎片相关联的活动实例,这样调用活动里的方法就变得垂手可得了。好比想在MyFragment获得MainActivity的实例:
MainActivity activity=(MainActivity)getActivity();
复制代码
因而碎片和活动能够很方便地进行通讯了。再想想碎片和碎片之间如何进行通讯?先在一个碎片中能够获得与它相关联的活动,而后再经过这个活动去获取另一个碎片的实例,这样实现了不一样碎片之间的通讯了。
如今你有没有想到解决以前那个问题的办法呢?能够这样作,修改MyFragment,代码以下图所示:
如今按钮点击就又有响应了!其实在实际开发中,若是某一板块每次用到都须要相同的功能,就彻底能够在碎片中实现需求,而没必要在活动中重复代码,这样能够提升代码的复用性。
> 下一篇预告:数据存储篇