}
}
Fragment有很多可以复写的方法,其中最常用的就是onCreateView()
,该方法返回Fragment的UI布局,需要注意的是inflate()的第三个参数是false,因为在Fragment内部实现中,会把该布局添加到container中,如果设为true,那么就会重复做两次添加,则会抛如下异常:
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child’s parent first.
如果在创建Fragment时要传入参数,必须要通过setArguments(Bundle bundle)方式添加,setArguments方法必须在fragment创建以后,添加给Activity前完成
,而不建议通过为Fragment添加带参数的构造函数,因为通过setArguments()方式添加,在由于内存紧张导致Fragment被系统杀掉并恢复(re-instantiate)时能保留这些数据
。官方建议如下:
It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated.
我们可以在Fragment的onAttach()
中通过getArguments()
获得传进来的参数,并在之后使用这些参数。
如果要获取Activity对象,不建议调用getActivity(),而是在onAttach()中将Context对象强转为Activity对象
。
创建完Fragment后,接下来就是把Fragment添加到Activity中。在Activity中添加Fragment的方式有两种:
- 静态添加:在xml中通过的方式添加,缺点是一旦添加就不能在运行时删除。
<?xml version="1.0" encoding="utf-8"?>
- 动态添加:运行时添加,这种方式比较灵活,因此建议使用这种方式。 虽然Fragment能在XML中添加,但是这只是一个语法糖而已,Fragment并不是一个View,而是和Activity同一层次的。
首先Activity需要有一个容器存放Fragment,一般是FrameLayout
,因此在Activity的布局文件中加入FrameLayout:
然后在onCreate()中,通过以下代码将Fragment添加进Activity中。
if (bundle == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, Fragment1.newInstance(“hello world”),“f1”)
//.addToBackStack(“fname”)
.commit();
}
这里需要注意几点:
因为我们使用了support库的Fragment,因此需要使用
getSupportFragmentManager()
获取FragmentManager,通过getSupportFragmentManager()
获取的FragmentManager只能管理Activity里面嵌入的所有一级fragment
。add()是对Fragment众多操作中的一种,还有
remove()
,replace()
等,第一个参数是根容器的id(FrameLayout的id,即”@id/container”),第二个参数是Fragment对象,第三个参数是fragment的tag名,指定tag的好处是后续我们可以通过Fragment1 frag = getSupportFragmentManager().findFragmentByTag("f1")
从FragmentManager中查找Fragment对象。在一次事务中,可以做多个操作,比如同时做
add()
.remove()
.replace()
。
commit()
操作是异步的,内部通过mManager.enqueueAction()
加入处理队列。对应的同步方法为commitNow()
,commit()
内部会有checkStateLoss()
操作,如果开发人员使用不当(比如commit()操作在onSaveInstanceState()之后),可能会抛出异常,而commitAllowingStateLoss()
方法则是不会抛出异常版本的commit()
方法,但是尽量使用commit(),而不要使用commitAllowingStateLoss()
。addToBackStack(“fname”)是可选的。FragmentManager拥有回退栈(BackStack),类似于Activity的任务栈,如果添加了该语句,就把该事务加入回退栈,当用户点击返回按钮,会回退该事务(回退指的是如果事务是add(frag1),那么回退操作就是remove(frag1));如果没添加该语句,用户点击返回按钮会直接销毁Activity。
Fragment有一个常见的问题,即Fragment重叠问题,这是由于Fragment被系统杀掉,并重新初始化时再次将fragment加入activity,因此通过在外围加if语句能判断此时是否是被系统杀掉并重新初始化的情况。解决方法有三种
- 第一种方式,在 Activity 提供的 onAttachFragment() 方法中处理:
@Override public void onAttachFragment(Fragment fragment) { super.onAttachFragment(fragment); if (fragment instanceof