Fragment中出现问题

1、Fragment not attached to Activity。

fragment还没有添加到Activity中,使用Context(上下文),无法获取null,getString()或者startActivity()出现异常

原因:在启动线程中调用getString()或者startActivity()等和activity相关api,有可能就是activity已经被销毁了,但是请求网络的线程还在继续执行,调用getString()或者startActivity()等就会出现异常

解决方案:加上isAdd()进行判断,if(isAdd()){//执行相关的逻辑}

2、实现Fragment中对回退键的监听

@Override

public voidonResume() {

super.onResume();

getView().setFocusableInTouchMode(true);//触摸是否能获取焦点

getView().requestFocus();//用键盘是否能获取焦点

getView().setOnKeyListener(newView.OnKeyListener() {

@Override

public booleanonKey(View v,intkeyCode, KeyEvent event) {

if(keyCode == KeyEvent.KEYCODE_BACK){

if(null!=mAct){

mAct.replaceFragment(0,false);

}

return true;

}

return false;

}

});

}

3、setFocusable(true)设置控件可以获取焦点,说明是有获取焦点的能力,并不是直接获取焦点   

requestFocus()设置要获取的控件

4、Can not perform this action after onSaveInstanceState

使用DialogFragment时候调用FragmentTransition.commit()方法出现问题,如果在Activity的onSaveInstanceState()方法后调用就会报错,调用onSaveInstance()方法说明activity马上要销毁,Activity一旦销毁也就无法添加Fragment。

解决方法:把commit()方法替换成 commitAllowingStateLoss()就行了,从名字上就能看出,这种提交是允许状态值丢失的。

4.1、在使用Fragment的过程中,常常会遇到在Activity的onSaveInstanceState方法调用之后,操作commit或者popBackStack而导致的crash.

因为在onSaveInstanceState方法之后的操作状态可能会丢失,因此Android framework默认会抛出一个异常.

对于commit方法来说,单纯避免这个异常很简单,使用commitAllowingStateLoss方法即可.但是popBackStack以及 popBackStackImmediate也都会检查state(checkStateLoss),特别需要注意的是Activity的 onBackPressed方法

如果onBackPressed在onSavedInstanceState之后调用,那么就会crash.

onBackPressed的调用时机:

* targetSdkVersion <= 5,在onKeyDown中调用

* targetSdkVersion > 5,在onKeyUp中调用

onSavedInstanceState的调用时机(如果调用的话):

* 一定在onStop之前

* 可能在onPause之前,也可能在onPause与onStop之间

需要注意的是: onSavedInstanceState方法不一定会调用,只有在Activity因为某些原因而被Framework销毁,并且之后还需要重新创建的情况,才需要调用(例如:旋屏,或者内存不足而回收返回栈中的某些Activity)

举例:

* Activity A在前台时,屏幕逐渐变暗直至锁屏,那么A的onSavedInstanceState会被调用

* Activity A start Activity B,Activity A的onSavedInstanceState会被调用

* Activity A因为返回键或者finish调用而返回到上一个界面,那么A的onSavedInstanceState不会被调用

因此,当onBackPressed在onSavedInstanceState方法之后调用,就一定会crash.解决方法主要有两种:

重写Activity的onSavedInstanceState()方法,并且注释掉super调用.

这种方法能避免crash,但是它会导致整个Activity的状态丢失.以DialogFragment为例,正常情况下,显示的 DialogFragment在旋屏Activity重新创建之后,不需要我们处理,Dialog会自动显示出来(参见 DialogFragment.onStart()),但是注释掉Activity的onSavedInstanceState()方法之 后,Fragment状态丢失,Activity重新创建之后,Dialog也就不会再显示出来了.

更好且通用的做法:在调用commit,popBackStack以及onBackPressed方法之前,判断 onSavedInstanceState()方法是否已经执行,并且onResume方法还没有执行,如果不是,那么直接操作,否则加入到 pending队列,等待onResumeFragments或者onPostResume之后再执行.

注意:不要在onResume中操作,因为这时候FragmentManager中的mStateSaved依然可能是true.(如果执行顺序是 onSavedInstanceState()->onPause()->onResume() 或者 onPause()->onSavedInstanceState()->onResume());

publicvoidendPaintingPager(intindex) {if(mFirstLevel ==PAINTING_PAGER) {

mFirstLevel=PAINTER_START;if(!mIsStateSaved) {

getSupportFragmentManager().popBackStack();

}else{

mPopBackStackRunnable=newRunnable() {

@Overridepublicvoidrun() {

getSupportFragmentManager().popBackStack();

}

};

}

}

}

@OverrideprotectedvoidonPostResume() {super.onPostResume();if(mPopBackStackRunnable !=null) {

mPopBackStackRunnable.run();

}

}

5、Attempt to invoke virtual method 'android.support.v4.app.FragmentTransaction android.support.v4.app.FragmentManager.beginTransaction()' on a null object reference

Fragment调用不保存状态dismissAllowingStateLoss(),show的时候传入getSupportFragmentManager()会报错,需要加上getSupportFragmentManager().beginTransaction()就解决问题

6、使用DialogFragment显示请求网络loading,快速点击报错

mainFragment already add :LoadingDialog


Fragment中出现问题_第1张图片
DialogFragment显示时序图

原因:主要是快速点击间隔时间比较短,调用dismiss通过handler传递消息,但是handler传递消息,有一定的延迟导致消息还未接收到,新的点击事件就已经执行最终让系统误认为上一个dialog已经存在,发生上面的错误。

解决方法:要让dialog的状态在新的点击事件之前刷新即可解决上面的问题

getSupportFragmentManager().execPendingActions();

if(!loadingDialog.isAdd()){

         loadingDialog.show(getSupportFragmentManager(),"loading");

}

Fragment加入到回退栈中出现的问题,如果当前fragment加入到回退栈中,然后重新回到整个fragment中通过EditText获取焦点后弹出小键盘,然后除了键盘地方被纯绿色的背景所覆盖,通过replace刷新fragment无效,最后解决方案就是在fragment所以来的activity中调用recreate方法刷新activity即可解决这个问题。

你可能感兴趣的:(Fragment中出现问题)