【问题标题】:Why it's recommended not to retain fragment with UI?为什么不建议在 UI 中保留 Fragment?
【发布时间】:2013-09-11 07:07:44
【问题描述】:

我读到使用 ui 和视图上的引用保留片段可能会导致内存泄漏。比我创建带有片段的测试应用程序,我在视图上存储一些引用并设置 setRetaineInstance(true),但是几次屏幕旋转不会导致任何泄漏。 MAT 说我只有一个父活动实例。我做错了什么?在哪些情况下使用 ui 保留 Fragment 会导致泄漏?

RetainInstanceActivity.java

public class RetainInstanceActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(android.R.id.content, RetainFragment.newInstance())
                .commit();
    }
}}

RetainFragment.java

public class RetainFragment extends Fragment {

private View mLogin;
private View mPassword;
private View ImageView;

public static RetainFragment newInstance() {
    final RetainFragment fragment = new RetainFragment();

    return fragment;
}

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);        
}

@Override
public View onCreateView(final LayoutInflater inflater,
        final ViewGroup container, final Bundle savedInstanceState) {       
    final View view = inflater.inflate(R.layout.fragment_retain, container,
            false);

    mLogin = view.findViewById(R.id.login);
    mPassword = view.findViewById(R.id.password);
    ImageView = view.findViewById(R.id.img);

    return view;
}

}

【问题讨论】:

  • 你在哪里看到过这种说法?
  • Here,例如。

标签: android memory-leaks android-fragments


【解决方案1】:

这里您保留对旧活动的 mLogin、mPassword 和 ImageView 视图的引用,但它们在旋转后立即被覆盖,因为 onCreateView() 将被调用,因此如果您的活动是前端活动并且发生配置更改,您应该没事。

但是,如果您的 Activity 不是最前面的 Activity,您可能会遇到内存泄漏,并且通常您无法知道片段是如何处理的。

例如 ViewPager 有 2 个不同的适配器,一个 (http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html) 保留 Fragment 实例(仅调用 onDestroyView()),而另一个 (FragmentStatePagerAdapter) 正在销毁 Fragment 实例。

因此,如果从 FragmentPagerAdapter 使用您的片段会泄漏大量内存。

我希望这是一个潜在问题的例子。如果您知道自己在做什么,那么调用 setRetaineInstance(true) 并且不释放视图就没有问题。

【讨论】:

  • 感谢您的回答,但这种方式似乎不起作用。我已经创建了一个带有两个适配器和一个带有十页的寻呼机的测试应用程序,但是在分页到最后、屏幕旋转和分页后,我留下了 10 个 FragmentPagerAdapter 的片段实例和 2 个 FragmentStatePagerAdapter 的实例。
  • 你必须把一个 ZIP 文件放在某个地方,有一个完整的项目供我查看,看看发生了什么
  • 你可以从这个repo获取项目。
  • 它完全按预期工作。 FragmentPagerAdapter 保留所有 10 个实例,而 FragmentStatePagerAdapter 仅保留可见实例及其邻居。你问的是内存泄漏,在这里你有它:屏幕旋转后,FragmentPagerAdapter 将在可见实例和它的 2 个邻居上调用 onCreateView,从而删除对按钮和图像视图的旧引用。其余 7 个实例将保留其旧引用,直到用户滑动查看它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2015-05-13
  • 2011-11-04
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
相关资源
最近更新 更多