Android(安卓)管理多个fragment(处理Activity被回收的情况)
做了好久的项目,由于进度赶,也没怎么闲心来写博客。不过项目赶是赶,也不是一口就能吞掉的,要慢慢来。既然慢慢来,就抽出点时间来写点什么。在项目里遇到好几个棘手的问题。有几个是被我解决掉。其中一个就是多个fragment的管理问题。只能说我是android的新手,也没怎么系统学习android,所以有些东西,只能在项目里摸索,要用到哪个就学哪个,还好我还大概知道哪些该在哪用,哪些该是被学。
情景一:一个Activity中使用多个fragment,以tab的形式来点击切换fragment。一共用到了4个fragment,用一个全局的fragment数组保存了所有fragment的引用。在onCreate方法中完成实例化(默认显示第一个fragment)。
mContentFragments = new BaseFragment[4];
这样会造成一个问题,就是比如:当前你切换到了第2个fragment,应用切换到了后天,这时候这个Activity在后台被回收了,然后你不知道,你切回应用,Activity又重新调用了activity方法。然后你就憋屈了,因为应用又回到第一个fragment。
解决办法(如有高手有其他解决办法请告知在下!):
由于我们一旦按了Home键,应用会转后台,aty会自动调用onSaveInstanceState保持状态,所以我们在onSaveInstanceState的方法里保存状态。aty在后台被杀死后,onSaveInstanceState中有保存状态,回到aty时会自动调用onRestoreInstanceState方法。
@Override protected void onSaveInstanceState(Bundle outState) { // mCurrentPosition表示当前切换的fragment的数组下标 outState.putInt(POSITIONKEY, mCurrentPosition); //super.onSaveInstanceState(outState); 总是执行这句代码来调用父类去保存视图层的状态,会导致fragmen重影,不能正常恢复状态 } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // 获取保存的数组下标 mCurrentPosition=savedInstanceState.getInt(POSITIONKEY); // 回复视图状态,恢复为fragmen的切换状态 changeTabView(savedInstanceState.getInt(POSITIONKEY)); super.onRestoreInstanceState(savedInstanceState); }
**情景二:**aty被回收了,fragment没被回收(还在内存中,只是我们没有它们的引用)!
先晾一下切换fragment的代码先:
public void changeFragment(int resView, Fragment targetFragment) { if (targetFragment.equals(currentFragment)) { return; } FragmentTransaction transaction = getFragmentManager() .beginTransaction(); if (!targetFragment.isAdded()) {// 如果这个fragment没被添加过 transaction.add(resView, targetFragment, targetFragment.getClass() .getName()); } if (targetFragment.isHidden()) {// 如果这个fragment是被隐藏的 transaction.show(targetFragment); } if (currentFragment != null && currentFragment.isVisible()) {// 隐藏当前显示的fragment transaction.hide(currentFragment); } currentFragment = targetFragment; // 提交了才算完成 transaction.commit(); }
在这里的代码,我使用的是FragmentTransaction里的add、show、hide方法,这样在fragment不多的情况下,可以保存fragment的状态,并提高了切换fragment的速度。但是这样的缺点在该情景下就有问题了。
aty被回收,fragment还在内存中,在FragmentManager里,重新onCreate,重新实例化了新的一批fragment,然后一调用changeFragment方法。比如,FragmentManager里有一个FragmentA,我们又重新实例化一个FragmentA。由于两个FragmentA的对象在堆中不是同一个,故FragmentTransaction会add这个新的FragmentA到FragmentManager中(会造成fragment重影),造成内存泄露。
所以,我们应该这么做(如有高手有其他解决办法请告知在下!):
@Override public void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { // 防止fragment没被回收 FragmentManager fm = getFragmentManager(); mContentFragments = new BaseFragment[4]; mContentFragments[0] = (BaseFragment) fm.findFragmentByTag(MainChatFragment2.class.getName()); mContentFragments[1] = (BaseFragment) fm.findFragmentByTag(MainCircleFragment.class.getName()); mContentFragments[2] = (BaseFragment) fm.findFragmentByTag(MainWallFragment.class.getName()); mContentFragments[3] = (BaseFragment) fm.findFragmentByTag(MainFindFragment.class.getName()); } super.onCreate(savedInstanceState); }
更多相关文章
- 关于 android app 返回键模拟 home键 功能的介绍_仿QQ返回键 又
- Android的多媒体技术――MediaPlayer实现音频与视频的播放
- Android之所以不需要关闭后台运行程序 的 理由
- Android热修复(一):底层替换、类加载原理总结 及 DexClassLoader类
- Android中View.setPressed是怎么出现按压效果的
- 浅析RxJava 1.x&2.x版本区别及原理(三):1.x 版本 Scheduler调度线程
- Android(安卓)进阶之了解源码——Activity启动
- Android中AsyncTask的简单用法及实现网络图片下载的实例
- 查看Android(安卓)API文档的正确方式