Fragment的使用和填坑

本文使用了以下文章的内容:YoKey的https://www.jianshu.com/p/fd71d65f0ec6

1 Activity与Fragment配合使用

单Activity+多Fragment

一个app仅有一个Activity,作为app容器使用,界面皆是Frament。

特点:性能高,速度最快。但逻辑复杂,尤其Fragment之间联动较多或者嵌套较深时。

多模块Activity+多Fragment

每个模块用一个Activity+多个Fragment,比如

1.登录注册流程:

LoginActivity + 登录Fragment + 注册Fragment + 填写信息Fragment + 忘记密码Fragment

2.或者常见的数据展示流程:

DataActivity + 数据列表Fragment + 数据详情Fragment + ...

优点:速度快,相比较单Activity+多Fragment,更易维护。

2 Fragment的使用要点

1.对Fragment传递数据

不要通过构造方法,应该使用setArguments(Bundle args),而后在onCreate中使用getArguments()取出。这样在 “内存重启”前,系统会保存数据,不会造成数据的丢失,这和Activity的Intent恢复机制类似。

2.Fragment对象的创建

Fragment内部定义静态方法newInstance(参数) 创建Fragment对象,优点是调用者只需要关系传递的哪些数据,而无需关心传递数据的Key是什么

3.Fragment使用宿主Activity对象

建议在基类Fragment定义一个Activity的全局变量,在onAttach中初始化,可以有效避免一些意外Crash,getActivity()空指针等。

4.FragmentManager

对于宿主Activity,getSupportFragmentManager()获取的FragmentActivity的FragmentManager对象;

对于Fragment,getFragmentManager()是获取的是父Fragment(如果没有,则是FragmentActivity)的FragmentManager对象;

对于Fragment,getChildFragmentManager()是获取自己的FragmentManager对象。

5.多个Fragment同时出栈

popBackStack(String tag,int flags)、popBackStack(int id,int flags)

popBackStackImmediate(String tag,int flags)、popBackStackImmediate(int id,int flags)

上面4个方法作用是,出栈到tag/id的fragment,即一次多个Fragment被出栈。

popBackStack和popBackStackImmediate的区别:前者是加入到主线队列的末尾,等其它任务完成后才开始出栈;后者是队列内的任务立即执行,再将出栈任务放到队列尾。尽量使用popBackStackImmediate(tag/id),而不是popBackStack(tag/id)。

6.Fragment转场动画(v4包下的Fragment)

getFragmentManager().beginTransaction().setCustomAnimations(enter,exit)

setCustomAnimations(enter, exit)只能设置进栈动画,第二个参数并不是设置出栈动画;

设置出栈动画请使用.setCustomAnimations(enter, exit, popEnter, popExit),这个方法的第1个参数对应进栈动画,第4个参数对应出栈动画。

3 Fragment填坑

1.getActivity()返回null

原因:是调用getActivity()时,当前的Fragment已经onDetach()了宿主Activity。

解决方法:在Fragment基类里设置一个Activity mActivity的全局变量,在onAttach(Activity activity)里赋值,使用mActivity代替getActivity(),保证Fragment即使在onDetach后,仍持有Activity的引用。

2.Can not perform this action after onSaveInstanceState

离开当前Activity等情况下,系统会调用onSaveInstanceState()帮你保存当前Activity的状态、数据等。

再回到该Activity之前(onResume()之前),执行Fragment事务,会抛出该异常!(其他Activity的回调让当前页面执行事务的情况)

3.Fragment重叠异常

在类onCreate()的方法加载Fragment,并且没有判断saveInstanceState==null或if(findFragmentByTag(mFragmentTag) == null),导致重复加载了同一个Fragment导致重叠。

if (savedInstanceState != null) {  // “内存重启”时调用

       targetFragment = getSupportFragmentManager().findFragmentByTag(TargetFragment.class.getName);

        hideFragment = getSupportFragmentManager().findFragmentByTag(HideFragment.class.getName);

        // 解决重叠问题       

        getFragmentManager().beginTransaction().show(targetFragment)

        .hide(hideFragment).commit();

    }else{  // 正常时       

        targetFragment = TargetFragment.newInstance();

        hideFragment = HideFragment.newInstance();

        getFragmentManager().beginTransaction()

                .add(R.id.container, targetFragment, targetFragment.getClass().getName())

                .add(R.id,container,hideFragment,hideFragment.getClass().getName())

                .hide(hideFragment)

                .commit();

    }

4.remove失效

如果没有将Fragment加入回退栈,remove方法可以正常出栈。

在add的同时将Fragment加入回退栈:addToBackStack(name)的情况下,remove()并不能真正将Fragment从栈内移除。popBackStack()系列方法才能真正出栈。

你可能感兴趣的:(Fragment的使用和填坑)