getSupportFragmentManager().getFragments() 抛出空指针异常
2016-02-17 16:46
519 查看
背景很简单,在一个FragmentActivity上显示我想要的fragment。
每次显示Fragment的时候我都调用一个函数:
该函数是找到该Activity上所有的Fragments,移除这些Fragments,然后加入我要显示的Fragment,将事务提交。
crash重现步骤:
在一个FragmentActivity上我先是显示了两个DialogFragment(标识为A和B,直接采用DialogFragment.show(…)方法),然后我将A和B都dismiss掉,显示另一个DialogFragment(标识为C,调用上述showFragmentInActivity的方法),然后我再dismiss掉C,显示另一个DialogFragment(标识为D,调用上述showFragmentInActivity的方法),此时抛出了如下的异常:
该错误是因为FragmentTransaction的add、remove、detach、attach函数如果传入的参数为null的话,在将事务提交的话,会抛出该异常。
在上述的函数中,我对传入的Fragment已经做过判空检查,所以add函数的参数不可能为空,只可能为remove函数的参数为空。remove的参数我是从getSupportFragmentManager().getFragments()中获取的,怎么可能为空呢。
查看了下getFragments的源代码:
从上述代码中看出mActive是用来存当前活跃(Active)的fragment的列表。
我又找到两段代码:
这两个函数是源代码内部调用的,我猜想makeActive函数应该是当一个fragment处于active的时候,将该fragment加入该列表中。如果一个Fragment不处于Active状态的时候,将该fragment所在的位置置为空。
非常重要的一点是,我在源代码中没有找到任何一处调用mActive.remove(…),只有mActive.add(…),这说明该列表只有加入,没有删除,只是置为空而已。所以难怪调用getFragments()函数返回的时候,可能存在空的元素(ArrayList是允许空的元素存在的)
解决办法就是在你从fragments中取出的时候,做一个判空就好了。
每次显示Fragment的时候我都调用一个函数:
public static boolean showFragmentInActivity(SdkFragment frag, String tag, SdkActivity actv) { if (frag == null || actv == null || actv.getSupportFragmentManager() == null) { return false; } FragmentTransaction transaction = actv.getSupportFragmentManager().beginTransaction(); if (transaction == null) { return false; } List<Fragment> fragments = actv.getSupportFragmentManager().getFragments(); for (int i = 0; fragments != null && i < fragments.size(); i++) { transaction.remove(fragments.get(i)); } transaction.add(frag, tag); transaction.commitAllowingStateLoss(); return true; }
该函数是找到该Activity上所有的Fragments,移除这些Fragments,然后加入我要显示的Fragment,将事务提交。
crash重现步骤:
在一个FragmentActivity上我先是显示了两个DialogFragment(标识为A和B,直接采用DialogFragment.show(…)方法),然后我将A和B都dismiss掉,显示另一个DialogFragment(标识为C,调用上述showFragmentInActivity的方法),然后我再dismiss掉C,显示另一个DialogFragment(标识为D,调用上述showFragmentInActivity的方法),此时抛出了如下的异常:
该错误是因为FragmentTransaction的add、remove、detach、attach函数如果传入的参数为null的话,在将事务提交的话,会抛出该异常。
在上述的函数中,我对传入的Fragment已经做过判空检查,所以add函数的参数不可能为空,只可能为remove函数的参数为空。remove的参数我是从getSupportFragmentManager().getFragments()中获取的,怎么可能为空呢。
查看了下getFragments的源代码:
ArrayList<Fragment> mActive; @Override public List<Fragment> getFragments() { return mActive; }
从上述代码中看出mActive是用来存当前活跃(Active)的fragment的列表。
我又找到两段代码:
void makeActive(Fragment f) { if (f.mIndex >= 0) { return; } if (mAvailIndices == null || mAvailIndices.size() <= 0) { if (mActive == null) { mActive = new ArrayList<Fragment>(); } f.setIndex(mActive.size(), mParent); mActive.add(f); } else { f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent); mActive.set(f.mIndex, f); } if (DEBUG) Log.v(TAG, "Allocated fragment index " + f); } void makeInactive(Fragment f) { if (f.mIndex < 0) { return; } if (DEBUG) Log.v(TAG, "Freeing fragment index " + f); mActive.set(f.mIndex, null); if (mAvailIndices == null) { mAvailIndices = new ArrayList<Integer>(); } mAvailIndices.add(f.mIndex); mActivity.invalidateSupportFragment(f.mWho); f.initState(); }
这两个函数是源代码内部调用的,我猜想makeActive函数应该是当一个fragment处于active的时候,将该fragment加入该列表中。如果一个Fragment不处于Active状态的时候,将该fragment所在的位置置为空。
非常重要的一点是,我在源代码中没有找到任何一处调用mActive.remove(…),只有mActive.add(…),这说明该列表只有加入,没有删除,只是置为空而已。所以难怪调用getFragments()函数返回的时候,可能存在空的元素(ArrayList是允许空的元素存在的)
解决办法就是在你从fragments中取出的时候,做一个判空就好了。
for (int i = 0; fragments != null && i < fragments.size(); i++) { /* 这里遇到一个exception,获取fragments的时候,返回的size为2,但是第二个fragment为空 * 如果remove、add、detach、attach方法的参数为空,则会抛出如下的异常: * java.lang.NullPointerException * at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:591)..... */ if (fragments.get(i) != null) { transaction.remove(fragments.get(i)); } }
相关文章推荐
- Ruby中的异常处理代码编写示例
- MySQL抛出Incorrect string value异常分析
- 浅谈C#中简单的异常引发与处理操作
- 详解C#编程中异常的创建和引发以及异常处理
- 详解JavaScript中的异常处理方法
- java程序中的延时加载异常及解决方案
- 解析Java异常的栈轨迹及其相关方法
- .NET(C#):Emit创建异常处理的方法
- windows7服务器上weblogic启动失败异常解决方法
- 有关ajax的error与后台的异常问题解决
- 深入探讨JAVA中的异常与错误处理
- GO语言异常处理机制panic和recover分析
- 浅谈JAVA 异常对于性能的影响
- 解析C++编程中的bad_cast异常
- C++ 异常处理 catch(...)介绍
- php中异常处理方法小结
- PHP中异常处理的一些方法整理
- 浅析Lua编程中的异常处理
- Perl中捕获警告信息、异常信息并写入日志详解
- 格式导致的Excel导入sql出现异常的解决方法