一、Fragment简介
Fragment(片段)表示Activity中的行为或用户界面部分。可以将多个片段组合在一个Activity中来构建多窗格UI,以及在多个Activity中重复使用某个片段。可以将片段视为Activity的模块化组成部分,它具有自己的生命周期,能接受自己的输入事件,并且可以在Activity运行时添加或删除片段。Fragment必须被嵌入一个Activity中,它们的生命周期直接受其宿主Activity的影响。
当Activity正在运行时,可以独立操纵每个片段,如添加或移除它们。当执行此类片段事务时,也可以将其添加到由Activity管理的返回栈——Activity中的每个返回栈条目都是一条已发生片段事务的记录。返回栈让用户可以通过按“返回”按钮撤销片段事务。
可以通过在Activity的布局文件中声明Fragment,将其作为<fragment>
元素插入Activity布局中,或者通过将其添加到某个现有ViewGroup,利用应用代码进行插入。
一个是系统内置的android.app.Fragment,一个是support-v4库中的android.support.v4.app.Fragment。建议使用support-v4库中的Fragment,因为它可以让碎片在所有Android系统版本中保持功能一致性。
二、Fragment优势:
- 可使开发人员将Activity分离成多个可重用的组件,每个都有自己的生命周期和UI;
- 可轻松创建动态灵活的UI设计,适应于不同的屏幕尺寸;
- Fragment做布局内容的更新更方便,原来需要把多个布局放到一个Activity里面,现在可用多Fragment来代替,只有在需要的时候才加载Fragment;
- Fragment 解决Activity间的切换不流畅,轻量切换;
- Fragment 替代TabActivity做导航,性能更好;
- Activity可同时组合多个Fragment,Fragment也可被多个Activity复用。
三、加载方式
1.静态加载
只需要把Fragment当成普通UI控件放到界面Layout中。
在布局文件中使用<fragment……/>
元素添加Fragment,<fragment……/>
元素的android:name
属性指定Fragment的实现类,注意要加上类的包名。
2.动态加载
碎片的强大之处就在于它可以在程序运行时动态地添加到活动当中。根据具体情况动态添加碎片,可以将程序定制地更加多样化。
需要先开启一个新事务,通过事务添加Fragment,提交事务,否则添加不成功。
1.创建待添加的碎片实例;
2.获取到FragmentManager,在V4包中通过getSupportFragmentManager,原生的Fragment是通过getFragmentManager获得的;
3.开启一个事务,通过调用beginTransaction方法开启;
4.向容器加入Fragment,一般使用add或replace方法实现,需要传入容器的id和Fragment的实例;
5.提交事务,调用commit方法提交。
四、生命周期
Fragment比Activity多了几个额外的生命周期回调方法:
- onAttach(): 当该Fragment被添加到Activity时被回调,该方法只会被调用一次。
- onCreateView(): 每次创建、绘制该Fragment的View组件时回调该方法,Fragment将会显示该方法返回的View组件。
- onActivityCreated(): 当Fragment所在的Activity被启动完成后回调该方法。
- onDestroyView(): 销毁该Fragment所包含的View组件时调用。
- onDetach(): 将该Fragment从Activity中删除、替换完成时回调该方法,在onDestroy()方法后一定会回调onDetach()方法,该方法只会被调用一次。
五、使用场景
有了Fragment就可以使用单个Activity+多个Fragment的方式,减少内存消耗、提升性能,且界面显示也更灵活。对于不同界面间有密切的逻辑关系且界面相似的场景,可以采用单个Activity+多个Fragment的方式。
- APP的主页面,点击不同的TAB按钮显示不同的界面;
- 用户的登录注册模块包括:登陆、注册、修改密码这三个界面的实现;
- 列表界面和列表项对应的详情界面这两种界面的实现,类似于订单列表和订单详情界面。
六、数据保存和恢复
1.临时保存数据和恢复
在以下场景需要临时保存当前Fragment使用的一些数据:
- 手机横竖屏切换时。
- 用户点击Home键,把当前界面切换到后台时。
- 手机锁屏时。
- 从当前Activity跳到另一个Avtivity,但不销毁之前的Activity时。
Fragement类和Activity类一样,也提供了onSaveInstanceState方法临时保存当前界面的数据,不过此方法是个空方法,需要开发者自己编写保存数据的代码。
public void onSaveInstanceState(Bundle outState){
……
}
在创建Fragment时,这个方法会在onStart方法之后被调用,横竖屏切换和当Fragment界面被切换到后台时,这个方法会在onPause方法之后被调用。
可在onCreateView和onActivityCreated等方法中进行数据恢复的处理。
2.持久保存数据和恢复
如需要持久保存数据,可将保存数据的代码放在onStop()和onDestroy()等方法中,恢复数据的代码放在onCreate方法中。
七、其他
1.在碎片中模拟返回栈
FragmentTranscation中提供了一个addToBackStack()方法,可以用于将一个事务添加到返回栈中,它可以接受一个名字用于描述返回栈的状态,一般传入null即可。
public class MainActivity extends AppCompatActivity implements View.OnClickLister{
……
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTrasaction();
transcation.addToBackStack(null);
transaction.commit();
}
}
2.碎片和活动间的通信
调用FragmentManager的findFragmentById()方法,可以在活动中得到相应碎片的实例,然后就能调用碎片的方法了。
在每个碎片中都可以通过调用getActivity()方法来得到和当前碎片相关联的活动实例。
MainActivity activity = (MainActivity) getActivity();
当碎片中需要使用Context对象时,也可以使用getActivity()方法,因为获取到的活动本身就是一个Context对象。