android 销毁fragment多个fragment怎么处理屏幕旋转

andoid学习(12)
& 在activity中使用fragment时,屏幕旋转时activity会被销毁重新创建。这是会再次创建一个新的fragment,使多个fragment重叠。这时我们只需要在AndroidManifest.xml文件中的activity配置中加一个&android:configChanges=&orientation|screenSize&的配置项,然后在代码activity中的onCreate方法中对savedInstanceState是否为空进行判断。if(savedInstanceState==null)时才创建fragment。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:21565次
排名:千里之外
原创:41篇
(1)(4)(1)(1)(2)(7)(7)(2)(11)(5)(1)(1)自从在Android 3.0引入Fragment以来,它被使用的频率也随之增多。Fragment带来的好处不言而喻,解决了不同屏幕分辨率的动态和灵活UI设计。但是在Activity管理多个Fragment中,通常会遇到这些问题:
1、Fragment的状态保存
2、Fragment的重影
当然,这些问题也一直出现我的开发过程中,虽然有时候通过各种手段也能解决一些问题,但是总是同时完美解决这两个问题。近来因为项目需要,查阅了很多官方资料(Android官方资料也慢慢有中文资料了,我大Google果然是Don't be evil,扯远了~~),终于彻底解决了这些问题。
设备:nexus 5
1、打开&不保留活动&(开发者选项里,主要用于模拟Activity被及时回收)
2、关闭&不保留活动&(正常状态下)
结果:目前没发现问题,由于设备有限,大家如果发现在其他设备上有问题,请在下方回帖!
首先我先来解释下上面问题出现的原因:
1、有时候,我们需要在多个Fragment间切换,并且保存每个Fragment的状态。官方的方法是使用replace()来替换Fragment,但是replace()的调用会导致Fragment的onCreteView()被调用,所以切换界面时会无法保存当前的状态。因此一般采用add()、hide()与show()配合,来达到保存Fragment的状态。以下为代码片段:
private void setTabSelection(int position) {
//记录position
this.position =
//更改底部导航栏按钮状态
changeButtonStatus(position);
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况
hideFragments(transaction);
switch (position) {
case TAB_HOME:
btnHomePager.setSelected(true);
btnShoppingCart.setSelected(false);
btnMine.setSelected(false);
if (homeFragment == null) {
homeFragment = new HomePagerFragment();
transaction.add(R.id.fragment_container, homeFragment);
transaction.show(homeFragment);
case TAB_SHOP:
btnHomePager.setSelected(false);
btnShoppingCart.setSelected(true);
btnMine.setSelected(false);
if (shoppingFragment == null) {
shoppingFragment = new ShoppingCartFragment();
transaction.add(R.id.fragment_container, shoppingFragment);
transaction.show(shoppingFragment);
case TAB_MINE:
btnHomePager.setSelected(false);
btnShoppingCart.setSelected(false);
btnMine.setSelected(true);
if (mineFragment == null) {
mineFragment = new MineFragment();
transaction.add(R.id.fragment_container, mineFragment);
transaction.show(mineFragment);
mitAllowingStateLoss();
2、第二个问题的出现正是因为使用了Fragment的状态保存,当系统内存不足,Fragment的宿主Activity回收的时候,Fragment的实例并没有随之被回收。Activity被系统回收时,会主动调用onSaveInstance()方法来保存视图层(View Hierarchy),所以当Activity通过导航再次被重建时,之前被实例化过的Fragment依然会出现在Activity中,然而从上述代码中可以明显看出,再次重建了新的Fragment,综上这些因素导致了多个Fragment重叠在一起。
我尝试了很多种方法去解决这个问题,比如:
在onSaveInstance()里面去remove()所有非空的Fragment,然后在onRestoreInstanceState()中去再次按照问题一的方式创建Activity。当我处于打开&不保留活动&的时候,效果非常令人满意,然而当我关闭&不保留活动&的时候,问题却出现了。当转跳到其他Activity、打开多任务窗口、使用Home回到主屏幕再返回时,发现根本没有Fragment了,一篇空白。
于是跟踪下去,我调查了onSaveInstanceState()与onRestoreInstanceState()这两个方法。原本以为只有在系统因为内存回收Activity时才会调用的onSaveInstanceState(),居然在转跳到其他Activity、打开多任务窗口、使用Home回到主屏幕这些操作中也被调用,然而onRestoreInstanceState()并没有在再次回到Activity时被调用。而且我在onResume()发现之前的Fragment只是被移除,并不是空,所以就算你在onResume()中执行问题一中创建的Fragment的方法,同样无济于事。所以通过remove()宣告失败。
接着通过调查资料发现Activity中的onSaveInstanceState()里面有一句super.onRestoreInstanceState(savedInstanceState),Google对于这句话的解释是&Always call the superclass so it can save the view hierarchy state&,大概意思是&总是执行这句代码来调用父类去保存视图层的状态&。其实到这里大家也就明白了,就是因为这句话导致了重影的出现,于是我删除了这句话,然后onCreate()与onRestoreInstanceState()中同时使用问题一中的创建Fragment方法,然后再通过保存切换的状态,发现结果非常完美。代码如下:
//记录Fragment的位置
private int position = 0;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
setTabSelection(position);
protected void onRestoreInstanceState(Bundle savedInstanceState) {
position = savedInstanceState.getInt("position");
setTabSelection(position);
super.onRestoreInstanceState(savedInstanceState);
protected void onSaveInstanceState(Bundle outState) {
//记录当前的position
outState.putInt("position", position);
记录于此,希望能帮助到一些正遇到这种问题的朋友!
阅读(...) 评论()10:38 提问
activity 旋转时 Fragment 重叠
我在程序中设置了一个 actionbar,在 actionbar 中有导航列表。我点击列表连续打开2个fragment,并显示在相同的activity中。
public void openFragment(AprilAppsFragment createdFragment){
if (createdFragment.getClass().isInstance(getDisplayedFragment()))
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.replace( R.id.main_fragment, createdFragment, "displayed fragment");
transaction.addToBackStack(null);
我先打开 fragment A,然后打开 fragment B,再旋转屏幕。Fragment A 被重新创建了导致程序崩溃。
如何避免重新创建fragment然后就不再显示?
按赞数排序
你的问题是没有为 fragments 保存状态,因为你没有添加android:configChanges="orientation|screenSize"。
因为你没有保存的状态应用程序崩溃,第一个 fragment 又调用一次。所以要在 manifest 中添加:
&activity android:name=".yourActivity" android:configChanges="orientation|screenSize"
重写 onSaveInstanceState 方法,保存 fragments的状态。
在 onCreate 中添加:
if(savedInstanceState != null){
fragmentA = (FragmentA) fragmentManager.getFragment(savedInstanceState, stringValueA);
fragmentB = (FragmentB) fragmentManager.getFragment(savedInstanceState, stringValueB);
然后检查 fragment 是否为空,然后创建它的实例,在 fragmentTransaction.relplace 中设置,或者在 openFragment 方法中设置。
你的问题是没有为 fragments 保存状态,因为你没有添加android:configChanges="orientation|screenSize"。
因为你没有保存的状态应用程序崩溃,第一个 fragment 又调用一次。所以要在 manifest 中添加:
&activity android:name=".yourActivity" android:configChanges="orientation|screenSize"
感谢 hxn_217的回答,我今天也遇到了这个问题
不过我只修改了AndroidManifest.xml中添加了
&activity android:name=".yourActivity" android:configChanges="orientation|screenSize"
并没有使用后面的步骤,也成功了。
其他相关推荐
其他相似问题君,已阅读到文档的结尾了呢~~
【精品】Android 屏幕旋转 处理 AsyncTask 和 ProgressDialog 的最佳方案-处理,和,屏幕,屏幕旋转,最佳方案,旋转屏幕,反馈意见
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
【精品】Android 屏幕旋转 处理 AsyncTask 和 ProgressDialog 的最佳方案-
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 android fragment使用 的文章

 

随机推荐