Fragment基本使用及存在的bug
Fragment基本使用
Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 当然现在他仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会加入这个Fragment, 我们可以把他看成一个小型的Activity,又称Activity片段!
Fragment静态使用
fragment我们可以在xml
布局文件中像UI控件一样使用。
<fragment
android:id="@+id/fragment_left"
android:name="com.example.basic.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
注意点:
- 静态fragment不能再嵌套fragment;
- 静态加载一旦添加就不能在运行时删除;
- 静态fragment 在onInflate() 中初始化;
- fragment一定要有一个无参构造方法。原因如下:
@Deprecated
@NonNull
public static Fragment instantiate(@NonNull Context context,
@NonNull String fname, @Nullable Bundle args) {
//...
Class<? extends Fragment> clazz = FragmentFactory.loadFragmentClass(
context.getClassLoader(), fname);
Fragment f = clazz.getConstructor().newInstance();
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.setArguments(args);
}
return f;
}
Fragment动态使用
Fragment动态使用的操作如下:
- 获得FragmentManager对象,通过getSupportFragmentManager();
- 获得FragmentTransaction对象,通过fm.beginTransaction();
- 调用add()方法或者repalce()方法加载Fragment;
- 最后调用commit()方法提交事务。
使用注意点与常见异常
注意点
- Fragment的onCreateView()方法返回Fragment的UI布局,需要注意的是inflate()的第三个参数是false;
- 如果在创建Fragment时要传入参数,必须要通过
setArguments(Bundle bundle)
方式添加,而不建议通过为Fragment添加带参数的构造函数; - 可以在Fragment的onAttach()中通过
getArguments()
获得传进来的参数。如果要获取Activity对象,不建议调用getActivity(),而是在onAttach()中将Context对象强转为Activity对象; commit
方法一定要在Activity.onSaveInstance()
之前调用;- FragmentManager拥有回退栈(BackStack)。
异常
1. getActivity() == null
原因:在网络请求返回数据后,页面已经关闭时,调用getActivity()会返回null。
解决方案: 不建议fragment要使用宿主activity getActivity。
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
2. Can not perform this action after onSaveInstanceState
解决方案:
a. 不能在onSaveInstanceState之后的生命周期里面commit fragment ;
b. 不要在子线程commit fragment 已经走完onSaveInstanceState。
3. Fragment重叠
原因:
- 屏幕旋转 activity 生命周期方法重新执行,而Fragment又具有自我恢复机制,故导致多次添加了该fragment。
不配置 "android:configChanges"时,
a. 竖屏--->横屏 ---> Activity重新执行1次生命周期
b. 横屏--->竖屏 ---> Activity重新执行2次生命周期
配置 "android:configChanges"相关属性后,不会再执行生命周期,只会调用onConfigurationChanged()。
2. 系统内存不足时会将切换至后台的app杀死,再次切换到前台时作恢复处理。
解决方案:
a. 在onSaveInstanceState()中注释掉super(缺点:activity失去自动存储的功能)
b. 添加fragment前,先判断savedInstanceState是否为null
// 添加fragment前,先判断savedInstanceState是否为null
if (savedInstanceState == null) {
// add fragment
}
setRetainInstance
如果想叫自己的Fragment即使在其Activity重做时也不进行销毁那么就要设置setRetainInstance(true)。进行了这样的操作后,一旦发生Activity重组现象,Fragment会跳过onDestroy直接进行onDetach(界面消失、对象还在),而Framgnet重组时候也会跳过onCreate,而onAttach和onActivityCreated还是会被调用。需要注意的是,要使用这种操作的Fragment不能加入backstack后退栈中。并且,被保存的Fragment实例不会保持太久,若长时间没有容器承载它,也会被系统回收掉的。