我读过在呈现 UI 的 fragment 上设置 .setOnRetainInstance(true)
可能会导致内存泄漏。
有人能解释一下为什么会发生这种情况吗?我在任何地方都没有找到详细的解释。
最佳答案
在带有 UI 的 Fragment
中,您经常将一些 View
保存为实例状态以加快访问速度。例如,一个指向您的 EditText
的链接,这样您就不必一直 findViewById
它。
问题在于 View
保留对 Activity
上下文的引用。现在,如果您保留 View
,您还保留了对该上下文的引用。
如果上下文仍然有效,但典型的保留情况是重新启动 Activity,那没问题。例如,经常用于屏幕旋转。 Activity 重新创建将创建一个新的上下文,而旧的上下文将被垃圾收集。但它现在不能被垃圾收集,因为你的 Fragment
仍然有对旧的引用。
下面的例子展示了如何不这样做
public class LeakyFragment extends Fragment {
private View mLeak; // retained
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mLeak = inflater.inflate(R.layout.whatever, container, false);
return mLeak;
}
@Override
public void onDestroyView() {
super.onDestroyView();
// not cleaning up.
}
}
要解决这个问题,您需要在 onDestroyView
中清除对 UI 的所有引用。一旦 Fragment
实例被重新使用,您将被要求在 onCreateView
上创建一个新的 UI。在 onDestroyView
之后保留 UI 也没有意义。 Ui 不会被使用。
此示例中的修复只是将 onDestroyView
更改为
@Override
public void onDestroyView() {
super.onDestroyView();
mLeak = null; // now cleaning up!
}
除了保留对 View
的引用之外,您显然不应该保留对 Activity
的引用(例如,来自 onAttach
- 在 上清理onDetach
)或任何 Context
(除非它是 Application
上下文)。
关于android - 带有 UI 和内存泄漏的保留 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13421945/