现在的位置: 首页 > 编程技术 > 安卓开发 > 正文

那些年我所踩过的fragment的坑(一)

2015年08月13日 安卓开发 ⁄ 共 1704字 ⁄ 字号 那些年我所踩过的fragment的坑(一)已关闭评论 ⁄ 阅读 199 次

看到这篇文章(Square:从今天开始抛弃Fragment吧!),再想想刚入职网易的时候,花了近一个星期解决了一个有关fragment的坑,不禁十分感慨,我要对Fragment进行“控诉”。

1.getActivity()==null?

看下如下两段代码,在fragment中加上如下一个方法

public void asd(){
if(getActivity()==null){Log.d("yes","it is null");}
}

然后在activity中加入fragment,如下:

FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();

你觉得执行完asd会怎么样?答案是有可能返回null。因为commit是异步的,并不能保证commit之后fragment立刻执行onAttach(Activity activity)方法,并且onDetach之后执行这个方法结果也可想而知。

2.fragment重叠

一般大家用fragment都是动态添加的,但是fragment会像View一样被activity的onSaveInstanceState方法所保存,所以,当你的app被系统回收,然后你再次开启时,你的activity里面系统会恢复一个fragment。如果你的写法是这样的就会出现问题

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mFragment = new FragmentDemo();
		FragmentManager fm = getFragmentManager();
		FragmentTransaction tx = fm.beginTransaction();
		tx.add(R.id.id_content, mFragment,"tag");
		tx.commit();
	}

你的id_content将会有两个FragmentDemo,新加的将会在以前恢复出来的上面也就是说的重叠。在屏幕旋转的时候也会出现重叠的情况。简单的解决办法是直接禁用onSaveInstanceState方法

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		//super.onSaveInstanceState(outState);
	}

但是这个办法同时会禁用了其他view控件的状态保存,比如Edittext。这个时候就需要我们检测savedInstanceState是否为null,如果为null直接添加,不为null则保持对恢复的fragment的引用(如果不正确的恢复引用会爆NullPointerException),代码如下:

if(savedInstanceState == null)
{
//add fragment
}else{
//don not add and find former fragment
mFragment=(FragmentDemo)getSupportFragmentManager().findFragmentByTag("tag");
}

如果你不在乎性能,那么最简单暴力的解决办法就是把最开始的

tx.add(R.id.id_content, mFragment,"tag");

改为

tx.replace(R.id.id_content, mFragment,"tag");

这样不管你的savedInstanceState是否为null,而R.id.id_content这个Container里面永远只会有最新的那个fragment,而你也拿到的正确的引用。

抱歉!评论已关闭.