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

Android fragment 重叠问题的解决方法

2016-04-01 17:29 543 查看
这边博客是想说一下在参考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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Fragment