Fragment坑
Fragment 常见坑
Fragment 踩过的坑
内存重启: app 运行在后台的时候,系统资源紧张的时候导致把 app 的资源全部回收(杀死 app 的进程),这时把 app 再从后台返回到前台的时候,app 会重启;回收之前,系统会把 Activity 的状态保存下来,Activity 的 FragmentManager 负责把 Activity 的 Fragment 保存起来。在内存重启后,Activity 的恢复是从栈顶逐步恢复,Fragment 会在宿主 Activity 的 onCreate () 方法调用后紧接着恢复 (从 onAttach () 生命周期开始)
1、getActivity () 空指针
原因:调用了 getActivity () 时,当前的 Fragment 已经 onDetach () 了宿主 Activity。
1
2
3
4
5
6
7
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
// mContext = getActivity();
}
- 切换 Fragment 的时候,会频繁的被 crash
- 系统内存不足
- 横竖屏幕切换的时候
以上情况都会导致 Activity 被系统回收,但是由于 fragment 的生命周期不会随着 Actiivty 被回收而被回收,因此才会导致 getActivity () 出现 null 的问题
解决:
- 利用 getApplicationContext ()
- Fragment 生命周期
在 Fragment 的生命周期中,在生命周期处于 onAttach () 和 onDetach () 之间的时候 getActivity () 方法才不会返回 null。
2、Fragment 重叠异常 —– 正确使用 hide、show 的姿势
见下面的 Fragment重影
3、Fragment 嵌套的那些坑
4、不靠谱的出栈方法 remove ()
5、多个 Fragment 同时出栈的那些深坑 BUG
6、超级深坑 Fragment 转场动画
Fragment 内存重启
- Android 解惑 - 为什么要用 Fragment.setArguments (Bundle bundle) 来传递参数
http://blog.csdn.net/tu_bingbing/article/details/24143249
其实就是在 Activity 重新创建 onCreate 的时候,会将 args 重新赋值给 Fragment,所以通过 setArguments 传递的会保留
- 一个 Activity 中,出现 crash,导致重启,白屏
关于Activity被回收,Fragment还在的问题 - Activity 后台运行一段时间回来 crash 问题的分析与解决
http://liuling123.com/2015/09/solution-crash-activity-back.html
后台 app,导致 getActivity () 为空
- Fragment 重叠 (重影) 问题
http://wml.farbox.com/post/fragment-overlay-problem
http://blog.csdn.net/leisurelife1990/article/details/51258749 - Android 管理多个 fragment (处理 Activity 被回收的情况)
http://www.kesarblog.cn/2016/01/11/Android-管理多个fragment-处理Activity被回收的情况/ - 关于 Android,用多个 activity,还是单 activity 配合 (详细,值得好好看) fragment?https://www.zhihu.com/question/39662488
Fragment 之 java. lang. IllegalStateException Can not perform this action after onSaveInstanceState
IllegalStateException: Can not perform this action after onSaveInstanceState:
#解决办法 :onSaveInstanceState 方法是在该 Activity 即将被销毁前调用,来保存 Activity 数据的,如果在保存玩状态后
再给它添加 Fragment 就会出错。解决办法就是把 commit()方法替换成 commitAllowingStateLoss ()
https://bugly.qq.com/v2/crash-reporting/crashes/d33adba520/495?pid=1
Fragment 重影之 add、hide、show
现象
假设底部有 3 个 tab: tab 1, tab 2, tab 3, 对应的引用分别为 Fragment 1 Fg、Fragment 2 Fg、Fragment 3 Fg;通过 FragmentManager 进行 add/show/hide 操作;切换到 tab 1, 此时 tab 1 = new Fragment 1 Fg (), 即 tab 1 变量指向 new Fragment 1 Fg ();这个时候, 按下 Home 长时间后台导致内存不足, 系统回收了 tab 1 的引用变成 tab 1 = null;而 tab 1 的实例还是存在内存中的,只是引用被销毁了,这时候切换到 tab 2,隐藏 tab 1,显示 tab 2,而 tab 1 已经为 null,无法实现 hide 操作,而由于 tab 1 的 Fragment 实例还在内存中,就会导致 tab 2 和 tab 1 重叠现象,再切换到 tab 1,由于 tab 1 为 null 会再次创建 tab 1 = new Fragment 1 Fg (),此时会再去创建一个新的 Fragment,放到 tab 1 上,导致原来的 tab 1 上的 Fragment 实例一直存在与内存中导致重影,置为被垃圾回收机回收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Fragment1fg f1;
Fragment2fg f2;
private void f11() {
FragmentTransaction transaction = manager.beginTransaction();
f1 = new Fragment1fg();
if (!f1.isAdded()) {
transaction.add(R.id.framelayout, f1);
}
if (f2 != null && f2.isAdded()) {
transaction.hide(f2);
}
transaction.commit();
}
private void f22() {
FragmentTransaction transaction = manager.beginTransaction();
f2 = new Fragment2fg();
if (!f2.isAdded()) {
transaction.add(R.id.framelayout, f2);
}
if (f1 != null && f1.isAdded()) {
transaction.hide(f1);
}
transaction.commit();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Fragment f1;
Fragment f2;
private void f11() {
FragmentTransaction transaction = manager.beginTransaction();
f1 = manager.findFragmentByTag("f1");
f2 = manager.findFragmentByTag("f2");
if (f1 == null) {
this.f1 = new Fragment1fg();
}
if (!f1.isAdded()) {
transaction.add(R.id.framelayout, this.f1, "f1");
} else {
transaction.show(f1);
}
if (f2 != null && f2.isAdded()) {
transaction.hide(f2);
}
transaction.commit();
}
private void f22() {
FragmentTransaction transaction = manager.beginTransaction();
f1 = manager.findFragmentByTag("f1");
f2 = manager.findFragmentByTag("f2");
if (f2 == null) {
f2 = new Fragment2fg();
}
if (!f2.isAdded()) {
transaction.add(R.id.framelayout, f2, "f2");
} else {
transaction.show(f2);
}
if (f1 != null && f1.isAdded()) {
transaction.hide(f1);
}
transaction.commit();
}
Ref
- Fragment全解析系列(一):那些年踩过的坑
- Fragment 全解析系列(二):正确的使用姿势
- Fragment 之我的解决方案:Fragmentation