我正在调查我们的应用程序中的outofmemoryerror bugreport。
我们的应用程序显示了一个列表视图,其中包含应用程序图标作为列表视图项目的一部分。
当使用标准baseadapter填充此列表视图时,会发现当包含它们的视图不在视线范围内时,应用程序不会保留在drawable中。
这也是使用弱引用进行测试的:
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驱动的listview时记录:
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()
然而,当我使用mergeAdapter时,它会填充交替的头文本视图和基本适应器,就像之前使用的那样,我得到的消息很少iconRecycled
。即使这些适配器在可用时也使用了recycleview。 (在滚动完整列表后,该应用程序的使用量为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()
这是我的实施中的错误吗?看起来mergeadapter以某种方式不再释放不在视图中的视图。这是对的吗?
修改
我通过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 »
答案 0 :(得分:0)
看起来mergeadapter以某种方式不再释放不在视图中的视图。这是对的吗?
如果“视图”是指“交替标题文字视图”,那么当然MergeAdapter
“不会释放不再在视图中的视图” - 如果MergeAdapter
发布了它们,当用户向后滚动时,MergeAdapter
无法显示它们,因为一旦释放,它就无法再将View
恢复。
如果“视图”中的意思是“像以前使用的那样的基础适应器”的内容,那么MergeAdapter
从不首先保留那些View
,因此不能持有它们。但是,getCount()
等方法的增加值可能会导致ListView
中的缓存更改。