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

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

mContentFragments = new BaseFragment[4];

这样会造成一个问题,就是比如:当前你切换到了第2个fragment,应用切换到了后天,这时候这个Activity在后台被回收了,然后你不知道,你切回应用,Activity又重新调用了activity方法。然后你就憋屈了,因为应用又回到第一个fragment。
解决办法(如有高手有其他解决办法请告知在下!):

Created with Raphaël 2.1.0 应用进入后台 调用onSaveInstanceState保持状态 aty在后台被杀死? 调用onRestoreInstanceState恢复状态 回到应用正常 yes no

由于我们一旦按了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);    }

更多相关文章

  1. 关于 android app 返回键模拟 home键 功能的介绍_仿QQ返回键 又
  2. Android的多媒体技术――MediaPlayer实现音频与视频的播放
  3. Android之所以不需要关闭后台运行程序 的 理由
  4. Android热修复(一):底层替换、类加载原理总结 及 DexClassLoader类
  5. Android中View.setPressed是怎么出现按压效果的
  6. 浅析RxJava 1.x&2.x版本区别及原理(三):1.x 版本 Scheduler调度线程
  7. Android(安卓)进阶之了解源码——Activity启动
  8. Android中AsyncTask的简单用法及实现网络图片下载的实例
  9. 查看Android(安卓)API文档的正确方式

随机推荐

  1. Android(安卓)跳转Activity并通过Bundle
  2. android 实现圆形进度条
  3. Android解析微博小尾巴
  4. RecyclerView竖直和水平的瀑布流布局
  5. Android通知工具类,含8.0通知适配,打开通知
  6. Android(安卓)Build System
  7. Android(安卓)TabWidget设计模板
  8. 基于Android的短信管理系统
  9. Android(安卓)webview 自动填值和提交
  10. Android那些“没用“知识(一)