问题:
应用从后台进入前台时,fragmeng中getActivity()获取null ,导致崩溃问题
原因:
当系统资源紧张时,或者被gc回收activity,但是进程还保留时,Activity都可能会被系统回收然后重建,在系统要把App回收之前,系统会把Activity的状态会保存下来,但Fragment并不会随着Activity的回收而被回收,创建的所有Fragment会被保存到Bundle里面,从而导致Fragment丢失对应的Activity。
void restoreChildFragmentState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(
FragmentActivity.FRAGMENTS_TAG);
if (p != null) {
if (mChildFragmentManager == null) {
instantiateChildFragmentManager();
}
mChildFragmentManager.restoreAllState(p, mChildNonConfig);
mChildNonConfig = null;
mChildFragmentManager.dispatchCreate();
}
}
}
第一种解决方法
在basefragment中处理onAttach,从生命周期上保证
@RequiresApi(23)
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
L.d("BaseFragment","Context的mContext是否为null"+(mContext==null));
}
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mContext = activity;
L.d("BaseFragment","Activity的mContext是否为null"+(mContext==null));
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getActivity();
}
/**
* 确保获取 不为null的上下文
* @return
*/
protected Context getBaseContext(){
if(mContext != null){
return mContext;
}else {
if(context != null){
return context;
}else {
//到这里,已经基本不能为null,getActivity()最好换成application的context
return getActivity();
}
}
}
第二种方法
不保存fragment的状态:在homeactivity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);
注释掉,让其不再保存Fragment的状态,达到fragment随homeactivity一起销毁的目的。
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("menuID", currentPage.menuID);
super.onSaveInstanceState(outState);
}
代码中有用到onSaveInstanceState ,该方法不适用。而且一般情况要处理savedInstanceState
第三种方法
重建时清除已经保存的fragment的状态:在恢复Fragment之前把Bundle里面的fragment状态数据给清除。
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("menuID", currentPage.menuID);
if(outState!=null){
outState.remove("android:support:fragments");
}
}
代码中有用到onSaveInstanceState ,该方法不适用。
目前第一种方法比较适用。或者重新处理homeactivity的onCreate(Bundle savedInstanceState)
中的savedInstanceState。