android4.0以后好像很强调使用fragment了,连ADT最新版本生成的默认工程中都运用了fragment,使用了才知道确实是好用很多,相当于将一个界面分成了很多个独立的部分,每个部分可以独立的实现自己的逻辑,且相互可以数据交互,很方便操作。当然,刚刚接触会嫌得很麻烦,慢慢用起来就好了。
今天fragment使用过程中出现了个问题,具体描述下:
首先,一般使用fragment都要在activity中onCreate方法里new一个fragment,然后添加到fragment管理器中并显示出来,如下:
<span style="font-size:18px;">// 主帖界面 Fragment fragment = new Fragment(); // 添加显示第一个fragment transaction.add(R.id.fragment_container, fragment).show(fragment).commit();</span>
那么,问题来了,我们new了一个fragment以后,fragment进入了自己的生命周期。当用户将当前activity切换到后台(是moveTaskToBack不是finish),这时候容器activity和fragment都进入onStop状态(调用了该方法,关于activity和fragment的生命周期自行脑补),而当手机内存不足神马的原因(挫手机)将咱的应用kill掉了,这时候重新打开应用,activity和fragment都保留下来,并重新执行onCreate->onStart->onResume方法,重点重点!!!activity又执行了一次new Fragment(),又一次将新fragment加入到了布局管理器,这时候应用将运行两个fragment!于是一切都不好了。。。同样的操作重复一次,应用又多了一个fragment,以此类推,子子孙孙无穷尽也~当然在两个fragment运行的时候程序已经不正常执行了。
很高兴能发现这个问题,看网上很多都是这样去初始化fragment的,坑了我好久,今天搞了一个多小时终于发现了这个问题,然后无脑补fragment生命周期,然后发现了activity中的:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
请注意,这个方法是带参数的,它带这东西是干嘛的?从来没用过啊!于是又观察了activity的生命周期,发现在activity的生命周期中,只要离开了可见阶段,或者说失去了焦点,activity就很可能被进程终止了!被KILL掉了,这时候,就需要有种机制,能保存当时的状态,这就是savedInstanceState的作用。
当一个Activity在PAUSE时,被kill之前,它可以调用onSaveInstanceState()来保存当前activity的状态信息(在paused状态时,要被KILLED的时候)。用来保存状态信息的Bundle会同时传给两个method,即onRestoreInstanceState() and onCreate()。
那么我找到一种解决方法:
if(savedInstanceState == null){ fragment = new <span style="font-size:18px;">Fragment</span>(); transaction.add(R.id.fragment_container, mainFragment, "mainFragment"); }else{ fragment = manager.findFragmentByTag("mainFragment"); } transaction.show(fragment).commit();
如上代码,先判断savedInstanceState是否为空,为空证明新来的,没有历史,那就new一个,但是在添加到transaction中时注意加一个tag,当savedInstanceState不为空时证明他是有历史的,不是被kill了就是被非正常kill了,于是为了避免出现多余的fragment,我从管理器中通过tag找到之前fragment,然后在显示出来,这样程序中还是一个activity和一个fragment在运行着,程序也就正常了。
小问题还是在不断测试中需求答案,网上给的可以参考到问题也很多,大家还有好的fragment的使用经验,谢谢分享。