Android fragment 重叠问题的解决方法

这边博客是想说一下在参考http://m.blog.csdn.net/article/details?id=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的问题。

解决问题时遇到的坑:
1、程序崩溃时只新建了一个fragment,程序崩溃后自动返回到此界面,这时界面是只显示这个fragment是正常的
2、当多个fragment全部新建完毕,程序崩溃掉之后自动返回到此界面时,多个fragment还是重叠在一起的,如下代码,在这里进行了恢复,但是fragment的状态确并没有保存下来,恢复的fragment的状态都是可见的,

 if (savedInstanceState != null) {
            selindex = savedInstanceState.getInt(PREV_SELINDEX);
            promotion = (PromotionFragment) manager.findFragmentByTag(flag[0]);
            classify = (ClassifyFragment) manager.findFragmentByTag(flag[1]);

            goods = (GoodsFragment) manager.findFragmentByTag(flag[2]);
            collect = (CollectFragment) manager.findFragmentByTag(flag[3]);
            mine = (MineFragment) manager.findFragmentByTag(flag[4]);
            Log.i("GAT", "state==="+classify.isHidden());
            Log.i("GAT", "state==="+goods.isHidden());
            Log.i("GAT", "state==="+collect.isHidden());
            Log.i("GAT", "state==="+mine.isHidden());
        }

log如下

04-01 17:08:29.587 24015-24015/com.lxrframe.promote I/GAT: state===false
04-01 17:08:29.587 24015-24015/com.lxrframe.promote I/GAT: state===false
04-01 17:08:29.587 24015-24015/com.lxrframe.promote I/GAT: state===false
04-01 17:08:29.587 24015-24015/com.lxrframe.promote I/GAT: state===false

所以需要在setTabSelection(selindex); 方法中将不需要显示的fragment手动隐藏掉

 FragmentManager manager = getSupportFragmentManager();
  FragmentTransaction tr = manager.beginTransaction();
                tr.hide(fm);
                tr.commit();

至此,问题解决,多谢楼主!!!!!
原文链接`http://m.blog.csdn.net/article/details?id=44036543

猜你喜欢

转载自blog.csdn.net/lantiankongmo/article/details/51038473