fragment是大家项目都会用到的,一般都是用来做选项卡的切换,切换时候每次都要进行网络请求,可是切换太快的话,网络请求还没完成就到下一个fragment了,这里记录一下使用fragment出现的错误以及解决办法。
错误信息1:
07-29 10:11:40.009: ERROR/AndroidRuntime(643): Caused by: java.lang.NullPointerException 07-29 10:11:40.009: ERROR/AndroidRuntime(643): at android.view.LayoutInflater.from(LayoutInflater.java:171) 07-29 10:11:40.009: ERROR/AndroidRuntime(643): at com.liumeng.adapter.MyListAdapter.< init >(MyListAdapter.java:23)
解决办法:
1、在onCreatView里面执行初始化操作
2、context使用之前判空
3、当出现这个问题时,只要在Fragment 中声明一个上下文类型的成员变量,并在onAttach()方法中将getActivity()的值赋给变量,在Fragment中使用到getActivity()时,都是用context即可。也就是说在将Fragment挂载到Activity时,就获得到了这个activity,并将这个activity保存起来了,这样就可以直接使用而不需要每次使用时都调用一遍getActivity()了。
4、MainActivity重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);注释掉,让其不再保存Fragment的状态,达到其随着MainActivity一起被回收的效果!
错误信息2:
解决办法:
是在使用FragmentTransition的 commit方法添加一个Fragment的时候出现的,后来在官网找到了相关的
说明:
public abstract int commitAllowingStateLoss () Added in API level 11 Like commit() but allows the commit to be executed after an activity’s state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
大致意思是说我使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState
方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错。解决办法就
是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。
错误信息3:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
在使用Fragment保存参数的时候,可能是因为需要保存的参数比较大或者比较多,这种情况下也会引起异####常。比如代码
Bundle b = new Bundle(); b.putParcelable("bitmap", bitmap2); imageRecognitionFragment.setArguments(b);
设置好参数,并且添加hide(),add(),方法之后,需要commit(),来实现两个Fragment跳转的时候,这种情形下参数需要进行系统保存,但是这个时候你已经实现了跳转,系统参数却没有保存。此时就会报如上错误。
解决办法:
你并不需要系统保存的参数,只要你自己设置的参数能够传递过去,在另外一个Fragment里能够顺利接受就行了,现在android里提供了另外一种形式的提交方式commitAllowingStateLoss(),从名字上就能看出,这种提交是允许状态值丢失的。到此问题得到完美解决,值的传递是你自己控制的。
这里也说一下另外一个问题,bitmap 也可以通过Bundle传递的,使用putParacelable就可以了
错误信息4:
java.lang.IllegalStateException: Fragment already added异常的处理。
当快速双击调用FragmentTransaction.add()方法添加fragmentA,而fragmentA不是每次单独生成的,就会引起这个异常。
DialogFragment.show()内部调用了FragmentTransaction.add()方法,所以调用DialogFragment.show()方法时候也可能会出现这个异常。
解决办法:
在add()方法时候,先判断fragmentA.isAdded(),如下调用可以避免该异常:
if(!fragmentA.isAdded()){ FragmentManager manager = ((FragmentActivity)context).getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); ft.add(fragmentA, "fragment_name"); ft.commit(); }
错误信息5:
Java.lang.IllegalStateException: fragment already active
最近遇到这个问题,fragment里有listview跳转到item的fragment页面时,setArguments传递一个Bundle参数。但是在连续点击item时,报出这个异常。
Java.lang.IllegalStateException: fragment already active
其实这个异常在源码里已经解释的非常清楚。
/** * Supply the construction arguments for this fragment. This can only * be called before the fragment has been attached to its activity; that * is, you should call it immediately after constructing the fragment. The * arguments supplied here will be retained across fragment destroy and * creation. */
也就是说,setArguments这个方法只能在fragment和activity绑定之前调用,而且其贯穿fragment的整个生命周期。
而我的问题在于,第一次点击item的时候,fragment已经setArguments后和activity进行了绑定,只是页面反应慢而已。而第二次点击,fragment已经和activity进行了绑定。自然fragment already active了。
有了问题,就要解决。查了下度娘谷哥好像不少人遇到这个问题。
方案一
就是利用getter,setter的方式来解决。这也是网上大多数的解决方法。
方案二
这个异常是fragment already active,我们可以想到可以判断fragment的active状态来控制是否和activity绑定。
public final boolean isVisible() Return true if the fragment is currently visible to the user. This means it: (1) has been added, (2) has its view attached to the window, and (3) is not hidden.
所以,我最后是这么解决的
if (!baseFragment.isVisible()) { Bundle bundle = new Bundle(); bundle.putString("params", str); baseFragment.setArguments(bundle); fx = fm.beginTransaction(); fx.add(R.id.main_fl, baseFragment, "BillList"); fx.addToBackStack(null); fx.commit(); }
欢迎start,欢迎评论,欢迎指正