嵌套片段在屏幕旋转后存活

时间:2014-06-11 21:21:03

标签: android android-fragments rotation android-nested-fragment

我遇到过Android中嵌套片段的问题。 当我旋转屏幕时,嵌套片段以某种方式存活。 我想出了一个示例来说明这个问题。

public class ParentFragment extends BaseFragment
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return  inflater.inflate(R.layout.fragment_parent, container);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

         getChildFragmentManager()
                 .beginTransaction()
                 .add(getId(), new ParentFragmentChild(), ParentFragmentChild.class.getName())
                 .commit();
    }

    @Override
    public void onResume() {
        super.onResume();
        log.verbose("onResume(), numChildFragments: " + getChildFragmentManager().getFragments().size());
    }     
}

public class ParentFragmentChild extends BaseFragment
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_child, null);
    }
}

BaseFragment只记录方法调用。 这就是我在旋转屏幕时看到的内容。

当活动最初出现时

ParentFragment﹕ onAttach(): ParentFragment{420d0a98 #0 id=0x7f060064}
ParentFragment﹕ onCreate()
ParentFragment﹕ onViewCreated()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{420d08d0 #0 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragmentChild﹕ onViewCreated()
ParentFragment﹕ onResume()
ParentFragment﹕ onResume(), numChildFragments: 1
ParentFragmentChild﹕ onResume()

屏幕旋转#1

ParentFragmentChild﹕ onPause()
ParentFragment﹕ onPause()
ParentFragment﹕ onSaveInstanceState()
ParentFragmentChild﹕ onSaveInstanceState()
ParentFragmentChild﹕ onStop()
ParentFragment﹕ onStop()
ParentFragmentChild﹕ onDestroyView()
ParentFragment﹕ onDestroyView()
ParentFragmentChild﹕ onDestroy()
ParentFragmentChild﹕ onDetach()
ParentFragment﹕ onDestroy()
ParentFragment﹕ onDetach()
ParentFragment﹕ onAttach(): ParentFragment{4211bc38 #0 id=0x7f060064}
ParentFragment﹕ onCreate()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{420f4180 #0 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragment﹕ onViewCreated()
ParentFragmentChild﹕ onViewCreated()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{42132a08 #1 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragmentChild﹕ onViewCreated()
ParentFragment﹕ onResume()
ParentFragment﹕ onResume(), numChildFragments: 2
ParentFragmentChild﹕ onResume()
ParentFragmentChild﹕ onResume()

屏幕旋转#2

ParentFragmentChild﹕ onPause()
ParentFragmentChild﹕ onPause()
ParentFragment﹕ onPause()
ParentFragment﹕ onSaveInstanceState()
ParentFragmentChild﹕ onSaveInstanceState()
ParentFragmentChild﹕ onSaveInstanceState()
ParentFragmentChild﹕ onStop()
ParentFragmentChild﹕ onStop()
ParentFragment﹕ onStop()
ParentFragmentChild﹕ onDestroyView()
ParentFragmentChild﹕ onDestroyView()
ParentFragment﹕ onDestroyView()
ParentFragmentChild﹕ onDestroy()
ParentFragmentChild﹕ onDetach()
ParentFragmentChild﹕ onDestroy()
ParentFragmentChild﹕ onDetach()
ParentFragment﹕ onDestroy()
ParentFragment﹕ onDetach()
ParentFragment﹕ onAttach(): ParentFragment{42122a48 #0 id=0x7f060064}
ParentFragment﹕ onCreate()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{420ffd48 #0 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{420fffa0 #1 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragment﹕ onViewCreated()
ParentFragmentChild﹕ onViewCreated()
ParentFragmentChild﹕ onViewCreated()
ParentFragmentChild﹕ onAttach(): ParentFragmentChild{42101488 #2 id=0x7f060064 com.kinoteatr.ua.filmgoer.test.ParentFragmentChild}
ParentFragmentChild﹕ onCreate()
ParentFragmentChild﹕ onViewCreated()
ParentFragment﹕ onResume()
ParentFragment﹕ onResume(), numChildFragments: 3
ParentFragmentChild﹕ onResume()
ParentFragmentChild﹕ onResume()
ParentFragmentChild﹕ onResume()

他们不断增加。有谁知道为什么会这样?

1 个答案:

答案 0 :(得分:6)

  

当我旋转屏幕时,嵌套片段会以某种方式存活。

他们生存的原因与ParentFragment幸存的相同,即使你不存在 使用setRetainInstance()保留实例。 FragmentManager就是这个原因, 在这种情况下,ChildFragmentManager ParentFragment用于处理嵌套片段。

您需要了解的一些事项:

  • FragmentManager负责管理片段和 将它们添加到活动的视图层次结构中。
  • FragmentManager处理两件事:
    • 片段列表(记住这个!)。
    • 返回堆栈碎片事务。
  • 添加删除附加分离替换 片段列表中的片段使用Fragment Transactions
  • 使用容器向FragmentManager询问片段时 view id(findFragmentById),如果片段已经在列表中, FragmentManager将返回它。然后你可以使用它。
  

最初显示活动时

由于应用程序刚刚启动,因此每个片段只有一个实例。其中一个ParentFragmentParentFragmentChild之一。到目前为止一切都很好。

  

屏幕旋转#1

此时,活动的FragmentManager和ParentFragment的ChildFragmentManager会保存其片段列表。然后,您可以看到两个片段是如何完全被破坏的。

重新创建活动时,新的FragmentManager将检索列表并且 重新创建列出的片段,使其在方向更改之前完成所有内容。请注意,这些是不同的实例,这些是由Android重新创建的新片段(这就是为什么你没有空构造函数就有片段,Android需要它来重新创建片段)。

现在,这是ParentFragment

中的代码
getChildFragmentManager()
             .beginTransaction()
             .add(getId(), new ParentFragmentChild(), ParentFragmentChild.class.getName())
             .commit();

您并未尝试查明ChildFragmentManager列表中是否已有ParentFragmentChild(已有)。这就是你可以看到两个片段被创建的原因,第一个是由ChildFragmentManager重新创建的,第二个是由前面的代码创建的。

  

屏幕旋转#2

在第二个方向更改之前,ChildFragmentManager列表中有两个ParentChildFragment,它们被重新创建,另外一个由代码创建。

最好使用FragmentManager重新创建的片段,而不是创建新片段。