setRetainInstance(true);未调用onAttach()方法。

3

我有一个父片段,它包含一个子片段。为了调试,这两个片段的onAttachonCreateView方法都被记录下来。

当我这样将父片段添加到Activity中:

parent.setRetainInstance(false);

旋转后的输出如下:
07-08 20:10:52.295: E/TAG(14216): Parent's onAttach called!
07-08 20:10:52.295: E/TAG(14216): Parent's onCreateView called!
07-08 20:10:52.305: E/TAG(14216): Child's onAttach called!
07-08 20:10:52.305: E/TAG(14216): Child's onCreateView called!

但是保留为:
parent.setRetainInstance(true);

旋转后的输出结果如下:
07-08 20:10:55.395: E/TAG(14216): Parent's onAttach called!
07-08 20:10:55.395: E/TAG(14216): Parent's onCreateView called!
07-08 20:10:55.400: E/TAG(14216): Child's onCreateView called!

总结一下,如果父片段是保留片段,则子片段的onAttach方法不会被调用(我假设onDetach也不会)。这个场景只是一个演示,实际上我需要调试一个复杂的应用程序以找出导致故障的原因。该应用程序存在内存问题,因为在方向更改后,子片段泄漏了先前的活动(作为在onAttach中设置的监听器)。
如果有人遇到同样的问题,解决方法可以是从父片段的onAttach手动调用子片段的onAttach
问题是:这是一个bug吗?
1个回答

2
当你使用setRetainInstance(true)时,片段会保留其配置(因此保留了对嵌套片段的引用,该引用从未真正分离/附加)。例如,在配置更改(如旋转)期间可能会发生这种情况。
所以这不是一个错误,而是Android的设计。
回答你的问题,你可以将Activity/Listener引用保留为WeakReference,这样当它不再需要时就会被释放。
另一方面,我会重新考虑整个想法,似乎你应该在onStop/onPause或类似的方法中订阅/取消订阅监听器/观察者。
注意:这并不能使事情变得更好,我讨厌Android的生命周期方法。

我知道配置是被保留的,但仍然有一个新的Activity要附加。旋转后不调用onAttach是具有误导性的,最好根本不要调用它。我可以从父级手动调用它,所以框架也可以这样做。我仍然认为这是一个错误。 - kupsef
WeakReference会在旋转后使Fragment变得无用,因为没有任何监听器可以调用。--> 没有使用新Activity的onAttached方法,旧引用在旋转后丢失。 - kupsef
父片段将在onAttach()中引用新活动,子片段可以从中获取它。 - ILovemyPoncho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接