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

iev*_*gen 0 android rotation android-fragments 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

BaseFragment只记录方法调用.这是我旋转屏幕时看到的.

当Activity最初出现时

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()
Run Code Online (Sandbox Code Playgroud)

屏幕旋转#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()
Run Code Online (Sandbox Code Playgroud)

屏幕旋转#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()
Run Code Online (Sandbox Code Playgroud)

他们不断增加.有人知道为什么吗?

ILo*_*cho 6

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

ParentFragment即使你没有保留这个实例,它们也会因为幸存而存活setRetainInstance().这FragmentManager就是原因,在这种情况下是处理嵌套片段ChildFragmentManagerParentFragment用途.

你需要知道的一些事情:

  • FragmentManager负责管理的碎片,并将它们添加到活动中的视图层次结构.
  • FragmentManager手柄两件事情:
    • 片段列表(记住这个!).
    • 返回堆栈的片段事务.
  • 添加,删除,连接,拆卸更换 在使用分片列表片段Fragment Transactions.
  • 当您FragmentManager使用容器视图id(findFragmentById)询问片段时,如果片段已经在列表中,FragmentManager则将返回它.然后你可以使用它.

当Activity最初出现时

由于应用程序刚刚启动,因此每个片段只有一个实例.其中一个ParentFragment和一个ParentFragmentChild.到现在为止还挺好.

屏幕旋转#1

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

重新创建Activity时,new会FragmentManager检索列表并重新创建列出的片段,以使其在方向更改之前生成所有内容.请注意,这些是不同的实例,这些是Android重新创建的新片段(这就是为什么没有空构造函数就无法拥有片段的原因,Android需要它来重新创建片段).

现在,这是你的代码ParentFragment:

getChildFragmentManager()
             .beginTransaction()
             .add(getId(), new ParentFragmentChild(), ParentFragmentChild.class.getName())
             .commit();
Run Code Online (Sandbox Code Playgroud)

你不是要试图找出它的列表中ChildFragmentManager已经有一个ParentFragmentChild(已经有).这就是你可以看到两个片段被创建的原因,第一个片段正在被重新创建ChildFragmentManager,第二个片段是由前面的代码创建的.

屏幕旋转#2

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

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