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。
解决办法(如有高手有其他解决办法请告知在下!):

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);
    }
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值