【问题标题】:Can't find the leak, on my fragment android code在我的片段 android 代码上找不到泄漏
【发布时间】:2016-02-02 12:21:56
【问题描述】:

我有一个 TabLayout,在每个选项卡下都有一个 Fragment(我使用的是 ArrayPagerAdapter)。我注意到,当我从一个选项卡多次切换到另一个选项卡时,我的内存使用量会增加很多。从我的堆快照中,我可以看到有很多 AutoCompleteTextView 实例。

所以我确信问题可能出在此处:

public class MyFragment  {
...
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ...
    final MultiAutoCompleteTextView eInput = (MultiAutoCompleteTextView) v.findViewById(R.id.TextInput);
    EditorListener mEditorListener = new EditorListener();
    eInput.setOnEditorActionListener(mEditorListener);
    eInput.addTextChangedListener(new WhitespaceWatcher());
    eInput.setAdapter(mDictionaryAdapter);
    eInput.setTokenizer(new SpaceTokenizer());
    ...
  }
...
  class EditorListener implements TextView.OnEditorActionListener
  {
  @Override
  public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
    ...
    MultiAutoCompleteTextView input = (MultiAutoCompleteTextView) textView.findViewById(R.id.TextInput);
    ...
  }
}
...
}

但我不明白问题出在哪里。

【问题讨论】:

  • 好吧,您加载的每个片段都会有一个AutoCompleteTextView 小部件。 ArrayPagerAdapter 的工作方式类似于 FragmentPagerAdapter,因为所有页面都保存在内存中。
  • 是的,我知道这一点。我的问题是 - 从我在 Android Studio 上的实例下可以看到 - 每次我切换选项卡时,都会出现一个 AutoCompleteTextView 的新实例。因此,如果我有 4 个选项卡并且我切换任何选项卡 4 次,我将获得 16 个 AutoCompleteTextView 实例。知道原因吗?谢谢。
  • 您需要追踪创建这些实例的位置。例如,onCreateView() 是被调用 4 次还是 16 次?如果是后者,请追踪您创建片段实例的位置,并查看它们是否被调用了 4 次或 16 次。 ArrayPagerAdapter 中肯定有可能存在错误——例如,我从未将它与 appcompat-v7 一起使用,而且据我所知,这两者会因为一些意想不到的原因而产生不良交互。
  • onCreateView() 每次我切换到包含 Fragment 的选项卡,或者当我切换到它附近的一个选项卡时(距离 == 1)都会调用。片段的实例只有 4 个,应该如此。
  • 好的,这实际上是预期的行为——至少,FragmentPagerAdapter 做同样的事情。这表明ArrayPagerAdapter 没有错,这是一种解脱。理论上,参考树中显示的参考可以帮助您弄清楚AutoCompleteTextView 上的内容,尽管我发现它们很难使用。您可以尝试使用LeakCanary,因为它往往会提供更集中的详细信息,说明可能的泄漏源。

标签: android-fragments memory-leaks android-widget commonsware


【解决方案1】:

致其他人:发帖人和我就这个问题进行了非 SO 讨论,发帖人创建了 this sample app 能够重现该问题。


经过一番努力,我终于可以让LeakCanary 工作了。它需要1.4-beta1 而不是运输1.3.1。我需要做的就是添加依赖项并根据LeakCanary 文档设置一个Application 子类。然后,启动应用程序并在活动出现后按 BACK。

你得到:

这到底是框架bug还是appcompat-v7及其具体子类MultiAutoCompleteTextView引入的东西,目前还不能说。但是,这绝对不是您代码中的错误。

从片段的onDestroyView() 中的MultiAutoCompleteTextView (setAdapter(null)) 中清除适配器应该可以防止它泄漏活动,但小部件本身仍然会泄漏。快速扫描相关代码并没有给我太大希望,即无需修改框架(对于MultiAutoCompleteTextView)或appcompat-v7(对于它的子类)就可以修复泄漏本身。

【讨论】:

  • 问题不仅限于appcompat-v7,甚至MultiAutoCompleteTextViewAutoCompleteTextView 使用本机活动和片段展示了该问题。我提交了a bug report,使用的是您的示例应用程序的修订版本,该版本消除了很多模板生成的杂物(以确保杂物不会导致问题)。
  • 干得好!感谢您帮助我理解问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多