FragmentTranscation中的重要函数
// 向Activity中添加一个Fragment
transaction.add(R.id.fl_content, secondFragment,FragmentSecond.TAG);
// 从Activity中移除一个Fragment,如果移除的Fragment没有添加到回退栈,这个Fragment将会销毁
transaction.remove(secondFragment);
// 使用另一个Fragment替换当前的,实际上就是remove与add的合体
transaction.replace(R.id.fl_content,secondFragment,FragmentSecond.TAG);
// 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.hide(secondFragment);
// 显示之前隐藏的Fragment
transaction.show(secondFragment);
// 将view从UI中移除,和remove不同,此时fragment的状态依然由FragmentManager维护
transaction.detach(secondFragment);
// 重建view视图,附加到UI上并显示
transaction.attach(secondFragment);
// 将当前fragment添加到回退栈
transaction.addToBackStack(null);
Fragment回退栈
Fragment的回退栈是用来保存每一次Fragment事务发生的变化,如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次保存的Fragment。一旦Fragment完全从回退栈中弹出,用户再次点击回退栈,则退出当前Activity。
特例:
1、replace与addToBackStack配合使用: addToBackStack保证了当前Fragment实例不会被销毁,但是由于replace,使得视图层级还是会被销毁。所以从其他Fragment返回到当前的fragment中时,仍然会重新按照代码绘制。
2、hide与addToBackStack配合使用:hide不会讲视图层级销毁,所以回退回来之后,不会重新绘制界面。显示的是之前的内容。
Fragment与Activity的通信
1、Fragment调用Activity中的方法:getActivity().XXX
2、Fragment调用Fragment中的方法:getActivity().getSupportManager…
3、Activity调用Fragment中的方法:通过getFragmentManager.findFragmentByTag或者findFragmentById()获得任何Fragment实例
4、通信优化
为了降低Fragment与Activity的耦合,而且不提倡Fragment调用另一个Fragment中的方法,Fragment应该由它的管理者来(Activity)决定如何操作。
在Fragment中写如下代码
// 定义一个回调接口,由Activity实现
public interface FtOneBtnClickListener {
void onFtOneBtnClick();
}
// Fragment中的button点击事件
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt:
if (getActivity() instanceof FtOneBtnClickListener) {
((FtOneBtnClickListener)getActivity())
.onFtOneBtnClick();
}
break;
default:
break;
}
}
特殊情况下的Fragment的生命周期
当屏幕旋转时,会对屏幕上的视图进行重新绘制。因为当屏幕发生旋转,Activity会发生重新启动,默认的Activity中的Fragment也会跟着Activity重新创建。所以,不断的旋转就不断绘制,这是一种很耗时的内存资源的操作
上面的意思就是说:屏幕旋转时,Fragment的onCreate()、onCreateView()方法会执行多次。
原因:当屏幕发生旋转时,Activity发生重新启动,默认的Activity中的Fragment也会跟着Activity重新创建;这就造成当旋转的时候,本身存在的Fragment会重新启动,然后当执行Activity的onCreate时,由于在onCreate方法中实例化了Fragment,所以Fragment会再次被实例化。
解决方法
默认的Activity中的onCreate()方法中savedInstanceState会存储一些数据,包括Fragment的实例。所以,我们简单改一下代码,判断只有在savedInstanceState==null时,才进行创建Fragment实例。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
oneFragment = new FragmentOne();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fl_content, oneFragment, FragmentOne.TAG);
transaction.commit();
}
}
现在Fragment不会重新创建了,但是还会重新绘制一次,所以可以在onSaveInstanceState方法中将数据保存,然后在onCreate或者onCreateView或者onActivityCreated进行恢复。