2016-11-27 131 views
3

我有一个奇怪的问题,让我生气!SupportFragmentManager,popbackstack和屏幕旋转

场景:

我有Activity A作为发射ActivityActivity B可被通过IntentActivity A

Activity A --> Activity B 

活动B开始具有初始Fragment呼叫它Fragment C中,它是在Activity B中例示如下:

if(getSupportFragmentManager().findFragmentByTag(FragmentC.TAG) == null) { 
     getSupportFragmentManager() 
       .beginTransaction() 
       .add(R.id.container, 
        FragmentC.newInstance(null), // optional bundle 
        FragmentC.TAG) 
       .commit(); 
} 

Fragment CI具有在ViewHolder这要求通过Fragment C.回到托管Activity乙此时的OnClickListener一个RecyclerView我开始FragmentTransaction(在Activity B)来替换当前Fragment C,称之为Fragment d和我这个交易添加到堆栈中:

getSupportFragmentManager() 
      .beginTransaction() 
      .setCustomAnimations(
        R.anim.fragment_slide_enter, 
        R.anim.fragment_slide_exit, 
        R.anim.fragment_slide_enter_pop, 
        R.anim.fragment_slide_exit_pop) 
      .replace(R.id.container, 
         FragmentD.newInstance(bundle), 
         FragmentD.TAG) 
      .addToBackStack(null) 
      .commit(); 

因此,在这一点上我有Activity B带Fragment d从Fragment C到Fragment d在后面堆栈中的交易,处理的背衬像这样:

@Override 
public boolean onSupportNavigateUp() { 
    onBackPressed(); 
    return true; 
} 

@Override 
public void onBackPressed() { 
    super.onBackPressed(); 
} 

导航工作正常向前或向后移动,从开始Actvity A,通过对Activity乙 - >Fragment d和背部。

问题:

但是,如果我在Fragment d和旋转屏幕,然后pop返回堆栈去Fragment C(取消交易),我看到一个空白的Fragment。更奇怪的是,所有Fragment C的生命周期方法OnCreate()OnCreateView(),OnActivityCreated()被调用,并且我有有效的数据/对象(通过设置断点检查)。

奇怪但是,如果我从FragmentÇ打算时做一个add交易 - >Fragment d,显然两者都同时在彼此的顶部显示,我旋转屏幕,按回,并删除事务有没有问题,显然不是一个解决方案,只是一个观察。

我已经搜索过,但我已阅读并尝试过的所有内容都不起作用。我已经实施了类似的事情,这工作正常,但我在这里挣扎 - 任何帮助将不胜感激。

编辑

如果应用goies进入暂停状态(单独留在家中和屏幕熄灭),然后再次唤醒,恢复,片段显示为它应该。我没有在onResume初始化,所以我不知道为什么这个工程。

回答

4

已解决问题

好的,感谢您的建议,但我自己解决了这个问题。

解决方案?很简单,我踢我自己!

当弹出我从来没有列入Fragment到“啪”的getId()返回堆栈:

的代码之前,依靠FragmentActivity弹出返回堆栈本身onBackPressed()。事实上,文档和方法应该照顾这一点:

/** 
* Take care of popping the fragment back stack or finishing the activity 
* as appropriate. 
*/ 
@Override 
public void onBackPressed() { 
    if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) { 
      super.onBackPressed(); 
     } 
} 

但是它似乎是在配置已被更改,并要返回堆栈弹出到以前的交易,这并不正常工作。该代码的解决办法是手动采取 “啪” 后退堆栈自己的:

前:

@Override 
public boolean onSupportNavigateUp() { 
    onBackPressed(); 
    return true; 
} 

@Override 
public void onBackPressed() { 
    super.onBackPressed(); 
} 

后(工作液):

@Override 
public boolean onSupportNavigateUp() { 
    onBackPressed(); 
    return true; 
} 

@Override 
public void onBackPressed() { 
    if (getSupportFragmentManager().getBackStackEntryCount() > 0) { 
      getSupportFragmentManager().popBackStack(getSupportFragmentManager() 
        .getBackStackEntryAt(0).getId(), 
        FragmentManager.POP_BACK_STACK_INCLUSIVE)); 
    } else { 
      super.onBackPressed(); 
    } 
} 

getId()文档状态:

/** 
* Return the unique identifier for the entry. This is the only 
* representation of the entry that will persist across activity 
* instances. 
*/ 
public int getId(); 

所以基本上只有在发生配置更改(托管Activity已被破坏并重新创建)后成功“弹出”后台堆栈的唯一方法是引用Fragments唯一的id

4

由于屏幕旋转,您的问题发生。

根据文档,每当设备配置发生变化时(例如用户旋转屏幕时),您的活动将被破坏并重新创建。当屏幕更改方向时,由于屏幕配置已更改且您的活动可能需要加载替代资源(例如布局),因此系统会销毁并重新创建前景活动。

在这种情况下,您的活动B再次启动初始框架C和所有的生命周期方法执行再次

解决方案

  1. 您可以限制在纵向模式下您的活动。
  2. 您应该处理方法在你的片段和onCreateView()

公共无效setRetainInstance(布尔保留) 控制定义setRetainInstance(true);片段实例是否可以通过活动的再创造留存(如从配置更改)。这只能用于不在后端堆栈中的碎片。如果设置,当活动被重建的片段生命周期会略有不同:

@Override 
    public void onConfigurationChanged(Configuration newConfig) { 
     super.onConfigurationChanged(newConfig); 

     // Checks the orientation of the screen for landscape and portrait 
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { 

     } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { 

     } 
    } 
+1

单独的'Fragments'和托管'Activity'处理配置更改没有问题。 –

+0

对于活动,您可以在清单文件中定义Configchanges属性。和片段,你可以重写onConfigurationChanged()方法就像我在解决方案中解释,让我知道如果你面临的问题 – NishchalAndroid

+0

你解决了你的问题? – NishchalAndroid

1

我以前也遇到了同样的问题。我想出了解决方案,满足我下面的代码要求 使用menifest的活动B

android:configChanges="keyboardHidden|orientation|screenSize" 

上面一行将不允许破坏你的活动,所以你不必片段破坏的问题

+1

个别'Fragments'和托管'Activity'处理配置更改相应 - 此解决方案不适合我遇到的问题。 –