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重叠

原因:

  1. 屏幕旋转 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实例不会保持太久,若长时间没有容器承载它,也会被系统回收掉的。





posted @ 2020-11-02 12:01  jxiaow  阅读(119)  评论(0编辑  收藏