Fragment的使用总结
fragment的产生
fragment是在android3.0引入的,主要目的是用在大屏幕设备上,比如平板。支持更加动态和灵活的ui设计。4.2之后新增fragment嵌套fragment的使用。
fragment的生命周期
fragment是必须依附于activity的,所以两者的生命周期也是有一定关系的。官网这张生命周期图就很好的解释了两者间的关系
对比以上两张图,我们发现fragment比activity多了几个生命周期。下面说下fragment生命周期的含义:
- onAttach():fragment和activity关联之后调用,也就是fragment依附上activity了。
- onCreate:fragment初次创建,这是fragment的创建而不是activity的。这是activity还没有创建完成呢。
- onCreateView:fragment的视图层构造完成。返回一个view
- onActivityCreate:activity的onCreate执行结束之后调用此方法。也就是activity创建完成。
- onStart:到这里的时候fragment的试图对用户是可见的了。和activity一样的,可见但不可交互。
- onResume:同activity的onResume,用户可交互
- onPause:同activity的一样
- onStop:同activity
- onDestroyView:和onCreateView相对应。销魂之前需要先销毁view。如果再次显示,则需要重新onCreateView
- onDestroy:销毁这个fragment,但是和activity不同的是,即使这个fragment执行了onDestroy,仍然能够在activity中找到。因为它还没有和activity解绑。
- onDetach:fragment生命周期的最后一个周期。就是和activity解绑,执行此方法后,所有的资源都被释放。
这里贴出activity和fragment运行时生命周期的执行顺序图:
fragment的两种简单的使用方式
方式一:静态添加fragment
- 编写fragment和其对应的布局文件
- 将fragment通过fragment标签和name属性添加到对应的activity的布局文件。
方式一:动态添加fragment
静态添加的方法是最简单的,但是fragment的使用和功能不仅限于此。回想手机app,导航切换页面是常见的,这就是动态添加。给我们的开发带来了极大的便利。主要步骤如下:
- 编写需要的fragment及其布局文件
- 在activity中编写导航布局和用来显示fragment的布局位置,记得添加id,后边要用到
在activity中捕捉导航tab的事件,动态添加或更换fragment
FragmentManager manager = getSupportFragmentManager(); //获取fragment管理器 FragmentTransaction transaction = manager.beginTransaction(); //开启事务 TestFragment fragment2 = new TestFragment(); //获取fragment实例 transaction.add(R.id.fragment_container, fragment2); //通过add或replace给指定的id的位置添加或更换指定的fragment transaction.commit(); //最后一定不能忘了的提交事务
使用有么有很简单。接着对上边用到的几个管理类做一下简单介绍:
FragmentManager
管理activity的fragment。常用的方法有:
- manager.findFragmentById(); //根据ID来找到对应的Fragment实例,主要用在静态添加fragment的布局中,因为静态添加的fragment才会有ID
- manager.findFragmentByTag();//根据TAG找到对应的Fragment实例,主要用于在动态添加的fragment中,根据TAG来找到fragment实例
- manager.getFragments();//获取所有被ADD进Activity中的Fragment
FragmentTransaction
用来管理当前的fragment,主要方法就是对fragment的add,replace,remove,hide,show,attach,deatch等
//将一个fragment实例添加到Activity的最上层
add(int containerViewId, Fragment fragment, String tag);
//将一个fragment实例从Activity的fragment队列中删除
remove(Fragment fragment);
//替换containerViewId中的fragment实例,注意,它首先把containerViewId中所有fragment删除,然后再add进去当前的fragment
replace(int containerViewId, Fragment fragment);
有关FragmentTransaction事务回滚的使用方法
上边介绍了FragmentTransaction的添加,删除和替换。如果想要上一次操作返回,就需要用到FragmentTransaction的回滚了。
回滚的使用方式:
在transaction.commit()之前,使用addToBackStack()将其添加到回退栈中。
在需要回退时,使用popBackStack()将最上层的操作弹出回退栈。这里默认弹出的是栈顶的事务,也可以根据id或tag来指定要弹出的事务
fragment的使用进阶–hide()、show()
场景描述
应用首页的tab页面来回切换时,每次都是加载fragment都会重新实例化,这样非常消耗性能和用户的数据流量,并且给用户的体验也不好。这是因为replace每次都把现有的fragment清空,再把指定的添加进去,这样就导致每次就会重新实例化fragment。
解决方案
首次add进去,切换时通过show和hidden来控制页面的现实和隐藏。
FragmentManager manager = (activity.getSupportFragmentManager());
FragmentTransaction ft = manager.beginTransaction();
boolean alive = false;
@SuppressLint("RestrictedApi") List<Fragment> fragments = manager.getFragments();
for (int i = 0; fragments != null && i < fragments.size(); i++) {
if(fragment == fragments.get(i)){//已经存在了
alive = true;
}
ft.hide(fragments.get(i));
}
if(alive){
ft.show(fragment);
}else{
ft.add(containerRes,fragment,tag);
ft.show(fragment);
}
ft.commit();
fragment间的数据传递
1、通过bundle传递,
Bundle args = new Bundle();
args.putString("param", text);
fragment.setArguments(args);
获取bundle:
getArguments()
2、接口回调实现(这种方式一般是fragment往fragment回传数据的时候使用)
在fragment中定义接口
set方法
调用接口
在activity中实现
3、eventbus实现
replace和add的区别
replace是会清空这个container中所有的fragment试图,注意是试图而不是这个fragment的实例。
add一般要配合hide使用,不允许添加同一个fragment实例,不然会报错。添加进来的这些fragment的试图都是可见的,绘制的时候全部都会绘制,最后添加的会展示在前边的上边。所以一般都要配合hide和remove使用,这样可以节省绘制的时间和内存的消耗