因为在之前文章中用到了fragment来显示地图与个人中心现在make一下fragment的相关知识。
具体fragment的不细说,简单知识点:
- Fragment跟Activity之间通信;
** Fragment与Activity绑定后
Fragment获取Activity对象;getActivity()获得Activity对象,就可以调用Activity方法了;
Activity中获取Fragment;
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
Fragment fragment = fragmentManager.findFragmentById(id);
获取Fragment后就可调用其方法了。
也可通过fragment.setArguments(Bundle)方法,将数据绑定到Fragment中。
- Fragment生命周期
Activity在生命周期中的状态:运行状态,暂停状态,停止状态,销毁状态。
Fragment在生命周期中也具有相同的状态。细节有区别:
** 运行状态
* Fragment可见,并所关联的Activity处于运行状态,则Fragment处于运行状态。
** 暂停状态
* Activity暂停(另一个Activity未占满Activity添加至栈顶)与其相关的可见的Fragment就会进入暂停状态。
** 停止状态
* ①Activity停止状态,与其相关联的Fragment就进入停止状态;
* ②FragmentTransaction的remove()、replace()方法将Fragment从Activity中移除,且在commit()前调用addToBackStack()方法;
停止状态的Fragment对用户完全不可见,有可能被系统回收。
** 销毁状态
* ①Fragment总是依附于Activity而存在,当Activity被销毁时;
* ②FragmentTransaction的remove()、replace()方法将Fragment从Activity中移除,且在commit()前没有调用addToBackStack()方法;
Fragment附加的回调方法:
onAttack()
- Fragment与Activity建立关联时调用;
onCreateView()
- 为Fragment创建视图(加载布局)时调用;
onActivityCreated()
- 确保与Fragment相关联的Activity已经创建完毕;
onDestoryView()
- 当与Fragment关联的视图被移除;
onDetach()
- 当Fragment与Activity解除关联。
- 当Fragment与Activity解除关联。
动态加载布局技巧
①使用限定符
- 双页(平板),单页(手机)
- 限定符(Qualifiers)large就是一个限定符
- 在layout文件下建立相应activity_main.xml文件(单页布局)
- 在res目录下新建layout-large文件夹,在该文件夹下新建布局也叫activity_main.xml(双页布局)
Android中常见的限定符:
②使用最小宽度限定符
large限定符到底指多大?什么样的设备会被认为是“large” ?
最小宽度限定符:Smallest_width Qualifier,对屏幕指定一个最小(以dp为单位),然后以这个最小值为临界点,屏幕宽度大于该值就加载一个布局,小于就加载另一个。在res目录下新建layout-sw600dp文件夹,在该目录下新建activity_main.xml。
Fragment的replace与add方法区别:
两种方法不同之处:是否要清空容器再添加fragment的区别,用法上add配合hide或是remove使用,replace一般单独出现。
Fragment并没有add与replace方法,FragmentManager的replace与add两种方法切换Fragment时的区别。
经常使用的一个框架 RadioGroup切换Fragment,每个Fragment就是一个功能模块。
case R.id.rb_1:
rb_1.setBackgroundColor(Color.RED);
transaction.show(fragment1);
// transaction.replace(R.id.fl, fragment1, "Fragment1");
break;
case R.id.rb_2:
rb_2.setBackgroundColor(Color.YELLOW);
// transaction.replace(R.id.fl, fragment2, "Fragment2");
transaction.show(fragment2);
break;
case R.id.rb_3:
rb_3.setBackgroundColor(Color.BLUE);
// transaction.replace(R.id.fl, fragment3, "Fragment3");
transaction.show(fragment3);
break;
该功能可通过replace与add两种方法实现:
该功能中Fragment的容器是一个FrameLayout;
- add——把所有的Fragment一层一层叠加到FrameLayout上;
- 不允许add同一个fragment实例,这是非常重要的特点。如果一个fragment已经进来的话,再次添加的话会报异常错误的。
- add进来的fragment都是可见的(visible),后add的fragment会展示在先add的fragment上面,在绘制界面的时候会绘制所有可见的view
- 每个Fragment只能添加一次,想要达到切换效果需要通过Fragment的hide与show方法结合,show要显示的hide其他的,该过程Fragment的生命周期没变化。
- 大多数add都是和hide或者是remove同时使用的。这样可以节省绘制界面的时间,节省内存消耗,是推荐的用法。
- replace——首先将该容器中的其他Fragment去掉然后与将当前Fragment添加到容器中。
- replace切换Fragment,每次都会执行上一个Fragment的onDestoryView和新的Fragment的onCreateView、onStart、onResume方法。
- replace会把容器中的所有内容全都替换掉,有一些app会使用这样的做法,保持只有一个fragment在显示,减少了界面的层级关系。
相同之处:每次add和replace都要走一遍fragment 的周期。
- 其实fragment一般不会这么简单使用,replace的使用场景一般不多,大多数是添加(add)和显示(show)配合隐藏(hide)来使用,这样首先避免相同类型的fragment的重复添加,提示开发者使用单例模式,已经添加过的fragment很多情况没有必要再次添加,而且还有把生命周期再走一遍,这是一种比较浪费的做法
最合适的处理方式是这样的:
1.在add的时候,加上一个tab参数
transaction.add(R.id.content, IndexFragment,”Tab1″);
2.然后当IndexFragment引用被回收置空的话,先通过
IndexFragment=FragmentManager.findFragmentByTag(“Tab1″);
找到对应的引用,然后继续上面的hide,show;
一种bug解释
Fragment实现类似Activity栈的压栈和出栈
Fragment的事务管理器内部维持了一个双向链表结构,该链表可以记录我们每次add的Fragment和replace的Fragment,然后back的时候帮助实现退栈操作。