本文使用了以下文章的内容: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()系列方法才能真正出栈。