Android 管理多个fragment(处理Activity被回收的情况)

做了好久的项目,由于进度赶,也没怎么闲心来写博客。不过项目赶是赶,也不是一口就能吞掉的,要慢慢来。既然慢慢来,就抽出点时间来写点什么。在项目里遇到好几个棘手的问题。有几个是被我解决掉。其中一个就是多个fragment的管理问题。只能说我是android的新手,也没怎么系统学习android,所以有些东西,只能在项目里摸索,要用到哪个就学哪个,还好我还大概知道哪些该在哪用,哪些该是被学。

情景一:一个Activity中使用多个fragment,以tab的形式来点击切换fragment。一共用到了4个fragment,用一个全局的fragment数组保存了所有fragment的引用。在onCreate方法中完成实例化(默认显示第一个fragment)。

java

mContentFragments = new BaseFragment[4];

这样会造成一个问题,就是比如:当前你切换到了第2个fragment,应用切换到了后天,这时候这个Activity在后台被回收了,然后你不知道,你切回应用,Activity又重新调用了activity方法。然后你就憋屈了,因为应用又回到第一个fragment。

解决办法(如有高手有其他解决办法请告知在下!):

“`flow

st=>start: 应用进入后台

e=>end: 回到应用正常

op1=>operation: 调用onSaveInstanceState保持状态

cond=>condition: aty在后台被杀死?

op2=>operation: 调用onRestoreInstanceState恢复状态

st->op1->cond

cond(yes)->op2->e

cond(no)->e

  1. 由于我们一旦按了Home键,应用会转后台,aty会自动调用onSaveInstanceState保持状态,所以我们在onSaveInstanceState的方法里保存状态。aty在后台被杀死后,onSaveInstanceState中有保存状态,回到aty时会自动调用onRestoreInstanceState方法。
  2. ```java
  3. @Override
  4. protected void onSaveInstanceState(Bundle outState)
  5. {
  6. // mCurrentPosition表示当前切换的fragment的数组下标
  7. outState.putInt(POSITIONKEY, mCurrentPosition);
  8. //super.onSaveInstanceState(outState); 总是执行这句代码来调用父类去保存视图层的状态,会导致fragmen重影,不能正常恢复状态
  9. }
  10. @Override
  11. protected void onRestoreInstanceState(Bundle savedInstanceState)
  12. {
  13. // 获取保存的数组下标
  14. mCurrentPosition=savedInstanceState.getInt(POSITIONKEY);
  15. // 回复视图状态,恢复为fragmen的切换状态
  16. changeTabView(savedInstanceState.getInt(POSITIONKEY));
  17. super.onRestoreInstanceState(savedInstanceState);
  18. }
  19. ```
  20. **情景二:**aty被回收了,fragment没被回收(还在内存中,只是我们没有它们的引用)!
  21. 先晾一下切换fragment的代码先:
  22. ```java
  23. public void changeFragment(int resView, Fragment targetFragment)
  24. {
  25. if (targetFragment.equals(currentFragment))
  26. {
  27. return;
  28. }
  29. FragmentTransaction transaction = getFragmentManager()
  30. .beginTransaction();
  31. if (!targetFragment.isAdded())
  32. {// 如果这个fragment没被添加过
  33. transaction.add(resView, targetFragment, targetFragment.getClass()
  34. .getName());
  35. }
  36. if (targetFragment.isHidden())
  37. {// 如果这个fragment是被隐藏的
  38. transaction.show(targetFragment);
  39. }
  40. if (currentFragment != null && currentFragment.isVisible())
  41. {// 隐藏当前显示的fragment
  42. transaction.hide(currentFragment);
  43. }
  44. currentFragment = targetFragment;
  45. // 提交了才算完成
  46. transaction.commit();
  47. }
  48. ```
  49. 在这里的代码,我使用的是FragmentTransaction里的add、show、hide方法,这样在fragment不多的情况下,可以保存fragment的状态,并提高了切换fragment的速度。但是这样的缺点在该情景下就有问题了。
  50. aty被回收,fragment还在内存中,在FragmentManager里,重新onCreate,重新实例化了新的一批fragment,然后一调用changeFragment方法。比如,FragmentManager里有一个FragmentA,我们又重新实例化一个FragmentA。由于两个FragmentA的对象在堆中不是同一个,故FragmentTransaction会add这个新的FragmentA到FragmentManager中(会造成fragment重影),造成内存泄露。
  51. 所以,我们应该这么做(如有高手有其他解决办法请告知在下!):
  52. ```java
  53. @Override
  54. public void onCreate(Bundle savedInstanceState)
  55. {
  56. if (savedInstanceState != null)
  57. {
  58. // 防止fragment没被回收
  59. FragmentManager fm = getFragmentManager();
  60. mContentFragments = new BaseFragment[4];
  61. mContentFragments[0] = (BaseFragment) fm.findFragmentByTag(MainChatFragment2.class.getName());
  62. mContentFragments[1] = (BaseFragment) fm.findFragmentByTag(MainCircleFragment.class.getName());
  63. mContentFragments[2] = (BaseFragment) fm.findFragmentByTag(MainWallFragment.class.getName());
  64. mContentFragments[3] = (BaseFragment) fm.findFragmentByTag(MainFindFragment.class.getName());
  65. }
  66. super.onCreate(savedInstanceState);
  67. }

来自为知笔记(Wiz)

时间: 2024-10-05 07:13:25

Android 管理多个fragment(处理Activity被回收的情况)的相关文章

Android开发之旅-Fragment和Activity之间onCreateOptionsMenu的联系

Fragment和Activity一样,可以重写onCreateOptionsMenu方法来设定自己的菜单,其实这两个地方使用onCreateOptionsMenu的目的和效果都是完全一样的,但是由于Fragment是从属于activity的,因此第一次使用onCreateOptionsMenu的时候需要注意以下知识点. 一.在Activity和Fragment中onCreateOptionsMenu的实现是有细微差别的: 在activity中: @Override public boolean

Android——Fragment和Activity之间的通信+Frangment生命周期

Android--Fragment和Activity之间的通信+Frangment生命周期 Fr'agment和Activity之间的通信 1.在Fragment中声明一个接口. 2.在Activity中实现在Fargment中声明的接口. 3.在Fragment中声明一个接口对象. 4.在Frangment的生命周期Onattach方法中判断当前Activity是否实现了此Fragment中声明的接口.如果已实现,就把当前Activity转换成接口对象. 5.调用Activity中实现的方法=

实现Android 动态加载APK(Fragment or Activity实现)

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38565345 最近由于项目太大了,导致编译通不过(Android对一个应用中的方法个数貌似有限制),所以一直琢磨着能否将某些模块的APK不用安装,动态加载,通过在网上查找资料和网友的帮助,终于实现了APK的动态加载,网络上介绍APK动态加载的文章非常多,但是我觉得写得非常好的就是这位大牛的,我基本上就是使用他的这种方案,然后加入了自己的元素.这位大牛是通过Activity实现的,我稍作修改

Android百日程序: Fragment动态管理和生命期

之前写过Fragment使用的程序,Fragment可以静态,也可以动态载入内存中的,这一章进一步看看如何动态地更换Fragment和看看Fragment生命期都有什么函数. 本章利用响应菜单点击事件,轮流载入不同的Fragment,显示不同的界面,效果如下: 开始的是没有载入Fragmen为空白: 点击菜单的NEXT FRAGMENT VIEW,就进入下一个界面,载入两个: 继续点击显示Fragment 1: 继续点击,显示Fragment2: 然后就是循环了: 如此循环显示不同画面. 一 首

Android应用开发:LoaderManager在Activity/Fragment中的使用分析

LoaderManager 外部接口initLoader:起始 public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { if (mCreatingLoader) { throw new IllegalStateException("Called while creating a loader"); } Loade

Android中Fragment与Activity之间的交互(两种实现方式)

(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如何创建Fragment混合布局做了详细的分析,今天就来详细说道说道Fragment与宿主Activity之间是如何实现数据交互的. 我们可以这样理解,宿主Activity中的Fragment之间要实现信息交互,就必须通过宿主Activity,Fragment之间是不可能直接实现信息交互的. Fragment与

Android 笔记-Fragment 与 Activity之间传递数据

Fragment 与 Activity之间传递数据有两种方法,一种是使用setArgument,一种是使用接口回调.下面先学习第一种方法. (1)使用setArgument方法: 为了便于理解,我在这里打个比喻:假如Activity是皇帝,它设立了三个部门(如三省六部),分别是Fragment1,Fragment2和Fragemnt3: 现在他现在要吩咐部门Fragment1去做一些事情,比如说:领兵攻打岛国!!好,它肯定不自己跑去告诉该部门的. 一般来说,会有个宰相或者太监总管来负责皇帝口谕是

Android笔记Fragment与Activity之间传递数据

Fragment 与 Activity之间传递数据有两种方法,一种是使用setArgument,一种是使用接口回调.下面先学习第一种方法. (1)使用setArgument方法: 为了便于理解,我在这里打个比喻:假如Activity是皇帝,它设立了三个部门(如三省六部),分别是Fragment1,Fragment2和Fragemnt3: 现在他现在要吩咐部门Fragment1去做一些事情,比如说:领兵攻打岛国!!好,它肯定不自己跑去告诉该部门的. 一般来说,会有个宰相或者太监总管来负责皇帝口谕是

Android中Fragment和Activity之间的互操作代码例子

摘要 本文介绍了Android中一个Activity中有多个Fragment的情况下,Fragment之间如何通过Activity进行互操作. 源代码 源代码地址为:http://download.csdn.net/detail/logicteamleader/8931199 源代码使用ADT编写,ADT版本为2014,Android版本为android-22. 技术要点 1.在Activity中的多个Fragment之间要互操作,一定要通过此Activity,不能直接通信: 2.在Activi