android - 带有 UI 和内存泄漏的保留 fragment

标签 android memory-leaks android-fragments

我读过在呈现 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/

相关文章:

java - 可扩展 ListView 上子项的 Intent

c++ - 编辑字符串时接收内存泄漏

java - 无需重启服务器即可清理Tomcat内存

java - 在android中使用Fragment标签时出现XML错误

android - 带有 Fragments 和 FragmentActivity 的 TabHost

android - 9 补丁按钮不显示文本

android - 如何在没有关闭先前 Activity 的情况下从通知中打开对话框样式的 Activity ?

android - 警告 : Different store and key passwords not supported for PKCS12 KeyStores. 忽略用户指定的 -keypass 值。在 Android Studio 中

c++ - SDL TTF 库内存泄漏(每帧创建和释放曲面)

android - 使用倾听来了解偏好变化