您的位置:首页 > 移动开发 > Android开发

Android fragment 重叠问题的解决方法

2016-11-17 16:33 591 查看


转载地址:http://blog.csdn.net/weizongwei5/article/details/44036543

由于这个项目的首页是类似微信的那种 tab 有四个界面 联系人,消息,动态,设置四个界面,因为有频繁的切换,所以就没有使用replace 和 remve方法。而是通过hide,show方式,这样虽然不会重复创建Fragment了,节省了view重绘的性能问题。
但是这样就容易导致一个问题:就是程序长时间后台导致fragment重叠。

    问题描述:
                    app运行的时候,按下home键,然后清理内存。 
                    或者,按下home之后,打开其他的一些占内存的app,然后把本app的内存挤掉了。

    解决方案:  (这个问题google了很多帖子,发现写的很乱,没几个好用的,后来我就一个个的试验,从两个帖子中找到有用的方法。综合如下:)
                    1:给每个Fragment加一个Tag;
                    2.在onCreate(Bundle savedInstanceState)中判断Bundle savedInstanceState是否不为空;
                    3.不为空则进行find Tag,重新给几个frament赋值。
                    
1.
switch (index) {
  case 0:
   // 当点击了消息tab时,改变控件的图片和文字颜色
   messageImage.setImageResource(R.drawable.message_selected); 
   messageText.setTextColor(Color.WHITE);
   if (messageFragment == null) {
    // 如果MessageFragment为空,则创建一个并添加到界面上
    messageFragment = new MessageFragment();
    transaction.add(R.id.content, messageFragment, FRAGMENT_TAG[index]);
   } else {
    // 如果MessageFragment不为空,则直接将它显示出来
    transaction.show(messageFragment);
   }
   break;

2.  3.
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.activity_main);
  // 初始化布局元素
  initViews();

  fragmentManager = getFragmentManager();
        if (savedInstanceState != null) {
            //读取上一次界面Save的时候tab选中的状态
            selindex=savedInstanceState.getInt(PRV_SELINDEX,selindex);
            messageFragment = (MessageFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[0]);
            contactsFragment = (ContactsFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[1]);
            newsFragment = (NewsFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[2]);
            settingFragment = (SettingFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG[3]);
        }
        // 选中index
  setTabSelection(selindex);
 }

//那么文中有几处蓝色高亮的代码  请看如下

    /**
     * Fragment的TAG 用于解决app内存被回收之后导致的fragment重叠问题
     */
    private static final  String[] FRAGMENT_TAG = {"msgfrag","contacfrag","actfrag","settfrag"};

PS:
            补充一点:PRV_SELINDEX,selindex  是用于恢复上一次界面Save的时候tab选中的状态

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //保存tab选中的状态
        outState.putInt(PRV_SELINDEX,selindex);
        super.onSaveInstanceState(outState);
    }

    /**
     * 上一次界面 onSaveInstanceState 之前的tab被选中的状态 key 和 value
     */
    private static final  String PRV_SELINDEX="PREV_SELINDEX";
    private int selindex=0;

OK,当你配置好了tag之后,再addfrag的时候使用了tag,Act执行saveInstancestates 的时候就会自动按tag给你保存frag的状态了。
那么,你如果觉得这种方式不是很好,你这tag也可以不要在add的时候使用,你可以在Act  onSAveInstancestate的时候,用FragmentMange手动保存,
然后在act,oncreate的时候bundle不为空 就用之前记录的几个tag手动打开。

这是这个act里面的Frag的问题。

2.那么frag中嵌套frag的时候,也是需要保存与恢复的呢?

frag中的frag是子frag,外层的frag是主frag。先这么叫吧,这样好区分。

一样的道理 ,代码都很像,你把主frag当成act,只是getSurpportFragmentManager的时候 ,不用这个方法,有个getChildFragmentManger,大概是这么写的吧,我记不清是getChildFfragmentMnager还是getSurpportChildFragmentmanager了,反正你找下就行了。

这里就不贴代码了,毕竟很act中潜逃frag代码都很像,逻辑都是一样的。

3.有点要注意的是viewpager中潜逃frag,这样的话 记得把Viewpager的缓存数设置为 frag 数目减一。viewpager有个方法是setoffscreenpagelimit方法,可以设置缓存数目,这个方法看viewpager的源码,意思是缓存下来未显示的子控件,所以viewpager肯定是有一个是显示的,其他的要缓存,那么缓存数是 子控件的数目减一。  而且从viewpager的源码上看,这个方法里,最小的数字是1。
 缓存数 默认也是1,你不改的话 他会 有一些问题,就是你这边的frag因为没有被缓存 会被自动释放,然后重新新建,有些逻辑执行的就比较多了 。
viewpager内嵌套frag之后,每次pagerAdapger  执行notifychange的时候会有个问题就是特么的,原来的旧的fragment会先释放,执行ondettach   ondestory方法  ,然后重新创建,要注意。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fragment