1

我在阅读FragmentRetainInstance sample. UiFragment中有变量RetainedFragment mWorkFragment。因此,旋转屏幕后,如何从内存中删除UiFragment?据我所知,mWorkFragment是一个在屏幕旋转和其他配置更改中存活的参考。对UI片段中保留片段的引用。旋转屏幕后,UI片段如何从内存中删除?

更新#1

我旋转的屏幕和按压启动GC,然后压转储堆。我看到UiFragment实例的数量是1.为什么?我期望看到2:1为当前的方向,1为先前的方向。

启动GC:

enter image description here

堆转储:

enter image description here

+0

'UiFragment'不被保留。如果它被保留,当主机Activity被重新创建时它不会被重新创建,这就是'Fragment#setRetainInstance(...)'的工作方式。所以,在你旋转屏幕并初始化一个gc之后,以前的'UiFragment'实例应该被垃圾回收。 –

+0

*如何从内存中删除UiFragment * - GC将从GC根目录(该UiFragment实例不是)开始,然后遍历其引用(依此类推)以查看哪些对象仍然需要。所以mWorkFragment引用并不重要,因为没有一个对象持久保持对UiFragment实例的引用来保持它活着。 – Luksprog

+0

@Luksprog,就我所知,从你的评论中,GC遍历从根开始的对象(可能是类'Application'),然后确定'UiFragment'是不可访问的(配置更改后没有引用)。所以它可以被删除。 'UiFragment'是无法访问的子树的根,'mWorkFragment'是'UiFragment'的子节点。如果根目录无法访问,则其所有子项都无法访问。对? –

回答

1

正如我在我的评论说,从你链接到样品UiFragment不泄露。它确实保留了对保留片段的引用,该保留片段在配置更改后仍然存在,但引用并不重要。 GC将从GC根开始,然后从那里遍历对象内部找到的引用之后的对象。由于UiFragment没有从生存的东西中引用(如RetainedFragment),它将在活动对象的层次结构之外,并且有资格进行垃圾回收。

如果您想查看内存泄漏,请在您链接的示例中,删除行mProgressBar = null;来自RetainedFragment的onDetach()回调。通过这种改变,RetainedFragment将持有对UiFragment(实际上是旧活动及其所有数据)的引用,使旧Context实例保持活动状态,至少在调用RetainedFragment的onActivityCreated()回调之前(onActivityCreated ()mProgressBar将被清除并指向已恢复的UiFragment的ProgressBar)。