隐藏片段的生命周期

时间:2015-11-08 09:01:53

标签: android android-fragments android-lifecycle

我想了解Android中活动生命周期和片段生命周期之间的交互,因此我决定启动一个新项目并从this page复制代码。
然后我认为为了提高我的理解力,在平板电脑上测试它,切换它的方向并看看它发生了什么是有用的(虽然它可能不适合这个)。 通过logcat,我跟踪了活动和国家片段上发生的主要事件,例如我写的Activity Oncreate:

Log.d("TAG", "Activity: 1.onCreate");

这是我从纵向视图开始然后旋转时得到的结果:

  

TAG:活动:1.onCreate
  标签:活动:2.onStart
  标签:## ContryFrag:1.onAttach
  标签:## ContryFrag:2.onCreateView
  标签:## ContryFrag:3.onStart
  标签:活动:3.onResume
  标签:## ContryFrag:4.onResume
  标签:活动:-3。因为
  标签:## ContryFrag:-4.onPause
  标签:活动:-2.onStop
  标签:## ContryFrag:-3.onStop
  标签:活动:-1.onDestroy
  标签:## ContryFrag:-2.onDestroyView
  标签:## ContryFrag:-1.onDetach
  标签:活动:1.onCreate
  标签:## ContryFrag:1.onAttach
  标签:## ContryFrag:1.onAttach
  标签:## ContryFrag:2.onCreateView
  标签:活动:2.onStart
  标签:## ContryFrag:2.onCreateView
  标签:## ContryFrag:3.onStart
  标签:## ContryFrag:3.onStart
  标签:活动:3.onResume
  标签:## ContryFrag:4.onResume
  标签:## ContryFrag:4.onResume

似乎在纵向视图中通过FragmentManager添加的片段仍然在旋转后重新创建,尽管它之前已被分离。即使不显示,也会再次跟踪恢复它的事件链 你能帮我理解这里发生的事吗?

修改

当我检查片段是否为InLayout()

Log.d("TAG", "## ContryFrag: 1.onAttach /" + isInLayout() );

我意识到旋转后有两个片段:一个用旋转创建,另一个似乎是前一个活动的剩余部分(不应该是)。

  

TAG:活动:1.onCreate
  标签:## ContryFrag:1.onAttach / false
  标签:## ContryFrag:1.onAttach / true
  标签:## ContryFrag:2.onCreateView / true
  标签:活动:2.onStart
  标签:## ContryFrag:2.onCreateView / false
  标签:## ContryFrag:3.onStart / false
  标签:## ContryFrag:3.onStart / true
  标签:活动:3.onResume
  标签:## ContryFrag:4.onResume / false
  标签:## ContryFrag:4.onResume / true

编辑2

这是我用来获取onSelectedCountry(String country)的虚拟代码,未提供:

public void onSelectedCountry(String country)
{
    String[] x = {country, "city0", "city1", "city2", "city3", "city4", "city5"};
    adapter.clear();
    adapter.addAll(x);
}

编辑3

这是my code。抱歉延迟,这是我第一次使用github。

3 个答案:

答案 0 :(得分:4)

Fragment添加FragmentManager后,它会一直保留在那里,直到您手动删除它或直到Activity永久结束。 (重新启动Activity,例如设备旋转时发生的情况不会导致它完成)

旋转设备不会清除碎片。如果您创建新的Fragment并在FragmentManager生命周期中随时将其添加到Activity,而无需先检查Fragment中是否已存在FragmentManager ,每次执行导致Fragment重新启动的任何操作时,您只需添加一个新的Activity

例如,此代码应仅允许添加一个片段副本。

protected void onResume() {

    String TAG = "COUNTRYFRAG";

    CountryFrag f = (CountryFrag) getSupportFragmentManager().findFragmentByTag(TAG);

    if (f == null) {
        f = new CountryFrag();
        getSupportFragmentManager().beginTransaction()
                .add(f, TAG)
                .commit();
    }

    int count = getSupportFragmentManager().getFragments().size();
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");

}

虽然每次旋转设备时都会添加一个新的。

protected void onResume() {

    String TAG = "COUNTRYFRAG";

        CountryFrag f = new CountryFrag();
        getSupportFragmentManager().beginTransaction()
                .add(f, TAG)
                .commit();

    int count = getSupportFragmentManager().getFragments().size();
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");

}

链接处的代码似乎使用savedInstanceState的存在来确定是否添加片段或是否从方法返回。这不可靠,因为您可能无法保存状态中的任何内容,因此它可能始终为null。最好特别检查一下你是否已经添加了片段。

if (savedInstanceState != null) 
            return;

答案 1 :(得分:0)

看起来您不使用片段的上一个实例。 当由于配置更改而重新启动Activity时,Android会保留Fragment布局和关联的后台堆栈。 看起来当重新创建Activity时会创建一个新片段。 尝试将以下代码添加到Activity的onCreate:

@Override
public void onCreate(Bundle savedInstanceState) {

        ...    

    ContryFrag fragment = (ContryFrag) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) {
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container, new ContryFrag());
        fragmentTransaction.commit();
    }
}

删除片段创建代码。

答案 2 :(得分:0)

链接文章包含在布局xml中定义的片段。您在github中的代码是按代码创建和添加片段。你在一起使用这两个吗?