【问题标题】:Mergeadapter memory leaking?合并适配器内存泄漏?
【发布时间】:2012-12-05 15:19:47
【问题描述】:

我正在调查我们应用程序中的内存不足错误报告。

我们的应用程序显示一个列表视图,其中应用程序图标作为列表视图项的一部分。

当使用标准 baseadapter 填充此列表视图时,可以观察到,当包含它们的视图消失时,应用程序不会保留可绘制对象。

这也是用弱引用测试的:

 public Drawable getIcon() {
        Log.v("AppResult", "getIcon()");
        Drawable icon = appInfo.loadIcon(pm);       
        leakTester.add(new WeakReference<Drawable>(icon));
        ArrayList<WeakReference<Drawable>> copy = new ArrayList<WeakReference<Drawable>>(leakTester); 
        for (WeakReference<Drawable> oldIcon: leakTester)
        {
            if (oldIcon.get() == null)
            {
                Log.v("AppResult", "iconRecycled");
                copy.remove(oldIcon);
            }
        }
        leakTester = copy;
        return icon;
    }

滚动浏览普通 baseadapter 驱动的列表视图时的日志:

12-05 16:17:57.450: V/AppResult(24890): getIcon()
12-05 16:17:57.450: V/AppResult(24890): iconRecycled
12-05 16:17:57.510: V/AppResult(24890): getIcon()
12-05 16:17:57.520: V/AppResult(24890): iconRecycled
12-05 16:17:57.580: V/AppResult(24890): getIcon()
12-05 16:17:57.590: V/AppResult(24890): iconRecycled
12-05 16:17:57.730: V/AppResult(24890): getIcon()
12-05 16:17:57.730: V/AppResult(24890): iconRecycled
12-05 16:17:58.510: V/AppResult(24890): getIcon()
12-05 16:17:58.510: V/AppResult(24890): iconRecycled
12-05 16:17:58.570: V/AppResult(24890): getIcon()
12-05 16:17:58.570: V/AppResult(24890): iconRecycled
12-05 16:17:58.650: V/AppResult(24890): getIcon()

但是,当我使用一个合并适配器时,它充满了交替的标题文本视图和基础适配器,就像之前使用的那样,我收到的iconRecycled 消息很少。即使这些适配器在可用时确实使用了回收视图。 (该应用程序的使用量达到 35MB!在滚动完整列表后,它在其他活动中保持在 12MB)。

12-05 16:15:04.800: V/AppResult(24890): getIcon()
12-05 16:15:04.860: D/dalvikvm(24890): GC_FOR_ALLOC freed 34K, 1% free 35857K/36167K, paused 26ms
12-05 16:15:04.860: V/AppResult(24890): getIcon()
12-05 16:15:04.910: V/AppResult(24890): getIcon()
12-05 16:15:04.910: V/AppResult(24890): getIcon()
12-05 16:15:04.910: V/AppResult(24890): iconRecycled
12-05 16:15:04.910: V/AppResult(24890): iconRecycled
12-05 16:15:04.950: V/AppResult(24890): getIcon()
12-05 16:15:04.950: V/AppResult(24890): getIcon()
12-05 16:15:04.950: V/AppResult(24890): getIcon()
12-05 16:15:13.260: V/AppResult(24890): getIcon()
12-05 16:15:13.430: V/AppResult(24890): getIcon()
12-05 16:15:13.590: V/AppResult(24890): getIcon()
12-05 16:15:14.300: V/AppResult(24890): getIcon()
12-05 16:15:14.370: V/AppResult(24890): getIcon()
12-05 16:15:14.440: V/AppResult(24890): getIcon()

这是我的实施中的错误吗?看起来合并适配器以某种方式不再释放不再可见的视图。这是正确的吗?

编辑

我通过 MAT 运行它,结果如下:

java.util.ArrayList[32] @ 0x413beb88  144 19.833.288 
  \mScrapViews android.widget.AbsListView$RecycleBin @ 0x4129bd9040 19.833.496 
    .\mRecycler android.widget.ListView @ 0x412c5db8  896 23.635.384 
      ..+mFocusedView, mRealFocusedView android.view.ViewRootImpl @ 0x4133fae8 440 1.776 
        ..|+this$0 android.view.ViewRootImpl$2 @ 0x4136f540 Native Stack 16 16 
        ..|+[1] android.view.ViewRootImpl[2] @ 0x41340930 » 24 24 
        ..|+this$0 android.view.ViewRootImpl$AccessibilityInteractionConnectionManager @ 0x413157e8 » 16 16 
        ..|\Total: 3 entries       
      ..+mServedView, mNextServedView android.view.inputmethod.InputMethodManager @ 0x413511f8 » 104 368 
      ..+listview com.denper.addonsdetector.ui.InstallDateLister @ 0x412d8bd8 »

【问题讨论】:

    标签: android memory-leaks


    【解决方案1】:

    看起来合并适配器以某种方式不再释放不再可见的视图。这是正确的吗?

    如果“视图”是指“交替的标题文本视图”,那么当然MergeAdapter“不再释放不在视图中的视图”——如果MergeAdapter 释放了它们,那么@987654323当用户向后滚动时,@ 无法显示它们,因为一旦释放,它就无法再次获取那些 Views。

    如果“视图”是指“像之前使用的那样的基本适配器”的内容,那么MergeAdapter 从一开始就不会持有那些Views,因此不能持有它们。但是,getCount() 等方法的值增加可能会导致 ListView 中的缓存更改。

    【讨论】:

    • 嗨,是的,我说的是基本适配器。如您所见,这不知何故导致了缓存问题。所以,我真的不明白为什么会发生这种情况,而且你也不是我所理解的?
    • @Peterdk:我当然不知道这方面有什么问题,也不知道MergeAdapter 有什么问题。您可能希望使用 MAT 来准确确认谁持有什么。
    • 我通过 MAT 运行它(请参阅更新的问题),它表明列表视图将所有视图保留在它的回收站中。根据其他一些信息,互联网是保存所有显示视图的地方。它们仅在以 convertview 形式提供时才会被删除。但是我确实使用了转换视图。由于mergeadapter,多个baseadapter不会从其他相等的adapter中获取回收视图。因此,在视图列表之间使用标题绝对不是一个好主意。
    • 可能和我没有实现getviewtype有关?那么它不会是一个合并适配器错误,将尝试。
    • @user4o01 查看 Commonsware 的最后一条评论。你需要重写这2个方法,让listview知道item是同一个viewtype,这样就可以回收了。
    猜你喜欢
    • 2016-04-21
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    相关资源
    最近更新 更多