android 6.0版本已经发布了很长时间了,相信大家都知道6.0 系统加入了运行时权限管理,一些危险权限需要在运行时申请。
现在有这么一种情况,如果在一开始用户授予了某项权限,比如定位权限或者相机权限,当应用程序已经启动了,用户手动按下主键之后,回到桌面,打开设置,进入该应用程序的权限管理界面,对该应用程序的权限进行手动取消和给与权限,这时候应用就会莫名其妙的重启,且不会执行activity 和 fragment的生命周期函数,但实质应用已经挂掉了,很奇怪的是app不会被crash掉,且没有任何日志。
如果项目中使用到了Fragment,再次点击应用图标将app从后台唤醒,会出现app崩溃提示,大概就是以下异常:
java.lang.IllegalStateException: Fragment does not have a view
at android.support.v4.app.Fragment$1.onFindViewById(Fragment.java:1933)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1234)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2046)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1989)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1092)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1234)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2046)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:174)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:598)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1238)
at android.app.Activity.performStart(Activity.java:6320)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2386)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2483)
at android.app.ActivityThread.access$900(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5441)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
- 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
这种情况是因为在权限设置界面取消或者取消后再重新手动给予该权限,再次进入该app时,里面的数据和对象已经被回收了但是有没有崩溃,界面还在。
这个问题该如何解决呢?
- 1
- 2
- 3
在activity中重写
@Override
protected void onSaveInstanceState(Bundle outState) {
// super.onSaveInstanceState(outState);
}
- 1
- 2
- 3
- 4
- 5
方法中注释掉
super.onSaveInstanceState(outState);
- 1
- 2
很好理解,在application被销毁后,系统要回收Fragment时,我们告诉系统:不要再保存Fragment。如此就解决了将app从后台唤醒,app出现该异常的问题。
重点:
但是这是一种取巧的方式,原因是什么呢,我这个android开发框架,在使用Fragment时使用构造函数传递参数,当Fragment被重建时,默认走无参构造函数,导致出现该异常。
所以在Fragment的基类里创建一个抽象函数
protected abstract int getLayout();
- 1
并在onCreatView里调用:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View v = inflater.inflate(getLayout(), null);
return v;
}
- 1
- 2
- 3
- 4
- 5
每一个Fragment都继承该基类,并实现getLayout()方法,设置布局ID。具体为:
@Override
protected int getLayout() {
return R.layout.fm_home;
}
- 1
- 2
- 3
- 4
另外向Fragment使用setArguments()+Bundle传参,注意在Fragment里接收参数时对getArguments()进行判空,防止空指针异常的出现。