一、什么是Fragment,为什么它会被称为第五大组件
Fragment是一个模块化和可重用的组件, 目的是为了解决不同屏幕分辩率的动态和灵活UI设计。
Fragment之所以被称为第五大组件是因为它比Activity更节省内存,其切换模式也更加舒适,使用频率不低于四大组件,且有自己的生命周期,但是必须依附于Activity。
Fragment的优点可以具体整理为如下几点:
Fragment 可以将 Activity 分离成多个可重用的组件,每个都有它自己的生命周期和 UI。
Fragment可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电脑,在不同的安卓设备上统一你的UI。
Fragment是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、交换等。
- Fragment 解决 Activity 间的切换不流畅,轻量切换。
- Fragment 替代 TabActivity 做导航,性能更好。
二、阐述一下Fragment的生命周期
官方的生命周期图说明了一切:
Fragment在Activity中启动,两者的的生命周期:
三、Fragment的添加方式
1.静态添加:在xml文件中指定name属性为Fragment
<fragment
android:name="com.baidu.fragmentdemo.BlankFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
2.动态添加:
- 需要在xml文件中指定一个FrameLayout,设置ID,充当Fragment的占位布局
- 在java代码中获取FragementManager对象,是一个Fragment的声明周期管理者
- 通过FragmentManager启动一个事务FragmentTransaction
- 通过FragmentTransaction对碎片进行一系列的操作:add/remove/hide/show…
5.调用FragmentTransaction.commit()提交事务
3.注意事项:
- 同一个Fragment对象只能被add一次
- 同一个FragmentTransaction只能提交一次
- transaction.addToBackStack(null); //将事务添加到返回栈中,此时按back键不会直接退出程序,先进入上一个碎片
四、Fragment的replce、add、remove分别是什么作用,replace 和 add方法有什么区别?
- replce:替换Fragment的栈顶页面
- add:添加Fragment到栈顶页面
- .remove:移除Fragment栈顶页面
replace 和 add方法的区别:
Fragment本身并没有replace和add方法, 这里的理解应该为使用FragmentManager的replace 和 add 两种方法切换Fragment时有什么不同。
- Fragment 的容器是一个 FrameLayout,add 的时候是把所有的 Fragment 一层一层的叠加到了 FrameLayout上了, 而replace的话首先将该容器中的其他Fragment去除掉然后将当前Fragment 添加到容器中。
- 一个 Fragment 容器中只能add一个 Fragment 种类,如果多次添加则会报异常,导致程序终止, 而 replace 则无所谓,随便切换。
- 因为通过 add 的方法添加的 Fragment,每个 Fragment 只能添加一次,因此如果要想达到切换效 果需要通过 Fragment 的的 hide 和 show 方法结合者使用。将要显示的 show 出来,将其他 hide 起来。这个过程Fragment的生命周期没有变化。
- 通过 replace 切换 Fragment,每次都会执行上一个 Fragment 的 onDestroyView,新 Fragment 的 onCreateView、onStart、onResume 方法。
五、Fragment 跟 Activity 之间是如何通信的?
Fragment向Activity传值:
第一种方法:在Fragment中法,通过getActivity(). 调用Activity中的公开方法;
第二种方法:在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity类实现这个接口,这样Fragment就能够调用这个回调方法,将数据传给Activity。
Activity向Fragment传值:
第一种方法:在Activity中调用Fragment的方法, getFragmentManager().findFragmentById(R.id.xxx);
第二种方法:创建Bundle数据包,并调用Fragment对象的setArguments方法, 之后在Fragment类中调用getArguments;
Fragment向Fragment传值:
第一种方法:通过宿主Activity调用另一个Fragment中的方法,getActivity().getFragmentManager().findFragmentById();
第二种方法:接口回调,在F1里面定义接口,Activity里面实现接口。通过回调实现F1与其父亲Activity的通信。在Activity接口回调方法里与F2通信,将参数传给F2;
第三种方法:使用广播,F1中将数据放在广播中发送,F2中接受广播,获取数据。
六、Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?
Fragment 的事务管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的 Fragment和 replace 的 Fragment, 然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。
七、FragmentPagerAdapter与FragmentStatePagerAdapter区别
FragmentPagerAdapter在生命周期Destroy方法中调用的是detach方法,只是将Fragment的UI和activity的UI锁脱离开来,并不回收内存,所以它适用页面较少的情况
FragmentStatePagerAdapter在生命周期Destroy方法中条用的是remove方法,在每次切换viewPager时回收内存,真正的释放了内存,所以它适用页面较多的情况,更节省内存