Android GridView 垃圾收集 (GC_EXTERNAL_ALLOC) <1K 过度热衷,导致 UI 非常不稳定

发布于 2024-12-12 02:42:08 字数 27303 浏览 0 评论 0 原文

我已经关注这个问题很长时间了,最​​后决定发布 - 我的 2xN GridView,它由带有单个图像和一段文本的单元格组成,很多时候非常不稳定(但有时非常平滑)。在检查 logcat 输出时,一旦开始滚动(列表中只有 12 个项目),我就会看到类似的内容:

10-25 17:28:40.420: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed 6K, 47% free 3383K/6279K, external 2044K/2161K, paused 38ms
10-25 17:28:40.510: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 36ms
10-25 17:28:40.600: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 40ms
10-25 17:28:41.805: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed 1K, 47% free 3383K/6279K, external 2044K/2161K, paused 34ms
10-25 17:28:41.840: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 25ms
10-25 17:28:41.880: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 25ms
10-25 17:28:41.910: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 20ms
10-25 17:28:41.940: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 18ms

这只是滑动到列表底部并返回的操作。非常不稳定。如果我继续上下滚动,GC 可能会继续滚动 5-6 次,然后停止。但是,一旦我按下菜单,弹出一个 2 条目菜单或切换活动并返回,GC 也会回来。

我关闭了图像的位图分配 - 同样的问题。我的细胞基本上是空的,但 GC 仍然发生。

我联系了 Romain Guy,他说我应该尝试分配跟踪。我运行跟踪并轻弹,但在我自己的代码中没有看到分配。我确实看到了分配,然后调用 Finalize中分配的com.android.internal.os.BinderInternal$GcWatcher,与logcat中的GC行数匹配。这是整个分配跟踪器转储(或作为图片,更容易解析)

1   24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
2   12  java.lang.Integer   5   java.lang.Integer   valueOf 
3   24  byte[]  5   dalvik.system.NativeStart   run 
4   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
5   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
6   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
7   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
8   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
9   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
10  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
11  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
12  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
13  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
14  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
15  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
16  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
17  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
18  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
19  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
20  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
21  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
22  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
23  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
24  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
25  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
26  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
27  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
28  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
29  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
30  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
31  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
32  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
33  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
34  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
35  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
36  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
37  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
38  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
39  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
40  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
41  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
42  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
43  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
44  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
45  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
46  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
47  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
48  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
49  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
50  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
51  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
52  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
53  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
54  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
55  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
56  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
57  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
58  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
59  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
60  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
61  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
62  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
63  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
64  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
65  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
66  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
67  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
68  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
69  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
70  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
71  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
72  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
73  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
74  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
75  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
76  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
77  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
78  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
79  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
80  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
81  8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
82  24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
83  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
84  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
85  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
86  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
87  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
88  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
89  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
90  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
91  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
92  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
93  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
94  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
95  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
96  8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
97  24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
98  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
99  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
100 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
101 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
102 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
103 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
104 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
105 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
106 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
107 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
108 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
109 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
110 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
111 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
112 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
113 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
114 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
115 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
116 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
117 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
118 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
119 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
120 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
121 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
122 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
123 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
124 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
125 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
126 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
127 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
128 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
129 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
130 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
131 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
132 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
133 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
134 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
135 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
136 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
137 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
138 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
139 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
140 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
141 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
142 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
143 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
144 20  java.util.ArrayList 19  android.os.MessageQueue <init>  
145 36  android.os.MessageQueue 19  android.os.Looper   <init>  
146 24  android.os.Looper   19  android.os.Looper   prepare 
147 144 java.lang.Object[]  19  java.lang.ThreadLocal$Values    initializeTable 
148 32  java.lang.ThreadLocal$Values    19  java.lang.ThreadLocal   initializeValues    
149 16  java.lang.VMThread  1   java.lang.VMThread  create  
150 40  java.util.WeakHashMap$Entry 1   java.util.WeakHashMap   put 
151 16  java.security.ProtectionDomain[]    1   java.security.AccessControlContext  <init>  
152 20  java.security.AccessControlContext  1   java.security.AccessController  getContext  
153 16  java.security.ProtectionDomain[]    1   java.security.AccessController  getStackDomains 
154 24  java.lang.String    1   java.lang.AbstractStringBuilder toString    
155 48  char[]  1   java.lang.AbstractStringBuilder <init>  
156 20  java.lang.StringBuilder 1   java.lang.Thread    create  
157 16  android.view.ViewRoot$2 1   android.view.ViewRoot   handleLongPress 
158 80  java.lang.Thread    1   android.view.ViewRoot   handleLongPress 
159 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
160 24  org.apache.harmony.dalvik.ddmc.Chunk    5   android.ddm.DdmHandleHeap   handleREAQ  
161 17  byte[]  5   android.ddm.DdmHandleHeap   handleREAQ  
162 24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
163 12  java.lang.Integer   5   java.lang.Integer   valueOf 
164 24  byte[]  5   dalvik.system.NativeStart   run 

:您可以看到,GC 之前以及每次 GC 之间发生的事件几乎如下所示:

107 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
108 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
109 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
110 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
111 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
112 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
113 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
114 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
115 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    

我真的希望分配跟踪器允许我使用单独的堆栈跟踪导出整个转储,但事实并非如此,所以我将粘贴一些堆栈跟踪这里,其中大部分与绘图有关:

android.graphics.Bitmap:

android.graphics.Bitmap nativeCreate    Bitmap.java -2  true    
android.graphics.Bitmap createBitmap    Bitmap.java 477 false   
android.view.View   buildDrawingCache   View.java   6716    false   
android.view.View   getDrawingCache View.java   6567    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1571    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.widget.AbsListView  dispatchDraw    AbsListView.java    1627    false   
android.widget.GridView dispatchDraw    GridView.java   1943    false   
android.view.View   draw    View.java   7022    false   
android.widget.AbsListView  draw    AbsListView.java    3005    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1646    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.view.View   draw    View.java   7022    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1646    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1644    false   

java.util.concurrent.CopyOnWriteArrayList:

java.util.concurrent.CopyOnWriteArrayList   iterator    CopyOnWriteArrayList.java   332 false   
android.view.ViewTreeObserver   dispatchOnPreDraw   ViewTreeObserver.java   570 false   
android.view.ViewRoot   performTraversals   ViewRoot.java   1293    false   
android.view.ViewRoot   handleMessage   ViewRoot.java   1899    false   
android.os.Handler  dispatchMessage Handler.java    99  false   
android.os.Looper   loop    Looper.java 130 false   
android.app.ActivityThread  main    ActivityThread.java 3691    false   
java.lang.reflect.Method    invokeNative    Method.java -2  true    
java.lang.reflect.Method    invoke  Method.java 507 false   
com.android.internal.os.ZygoteInit$MethodAndArgsCaller  run ZygoteInit.java 907 false   
com.android.internal.os.ZygoteInit  main    ZygoteInit.java 665 false   
dalvik.system.NativeStart   main    NativeStart.java    -2  true    

这是我的GridView容器XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <LinearLayout
    android:id="@+id/scroll_items_holder"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:background="@drawable/app_bg"
    android:orientation="vertical" >
    <LinearLayout
      android:id="@+id/buttonsLayout"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center" >
    </LinearLayout>
    <GridView
      android:id="@+id/gridview"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:columnWidth="150dp"
      android:gravity="right"
      android:horizontalSpacing="0dp"
      android:listSelector="@null"
      android:numColumns="auto_fit"
      android:paddingLeft="5dp"
      android:paddingRight="5dp"
      android:stretchMode="columnWidth"
      android:verticalSpacing="10dp" />
  </LinearLayout>
  <include layout="@layout/menu_bar_inc" />
</LinearLayout>

每个GridView单元格的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/card"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" >
  <ImageView
    android:id="@+id/thumbnail"
    android:layout_width="fill_parent"
    android:layout_height="120dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="5dp"
    android:scaleType="centerCrop" />
  <TextView
    android:id="@+id/show_name"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:ellipsize="marquee"
    android:maxLines="1"
    android:textColor="@color/white"
    android:textStyle="bold" />
</LinearLayout>

适配器,其中大部分被注释掉:

package com.tunerfish.tunerfish.adapters;

import java.util.ArrayList;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.tunerfish.tunerfish.core.TfHomeActivity;
import com.tunerfish.tunerfish.databasemanager.dataitem.EntityDataItem;
import com.tunerfish.tunerfish.ui.R;

public class TrendingGalleryAdapter extends BaseAdapter {

  // structure for dumb view holders
  public static class ViewHolder {
    public TextView showName;
    // public ImageViewWithLoader thumbnail;
  }

  // structure for actual data behind the ListView
  public static class EntityData {
    public EntityDataItem entityDataItem;
  }

  public final ArrayList<EntityData> mEntityDataList;

  private final LayoutInflater mInflater;

  public TrendingGalleryAdapter(TfHomeActivity context, ArrayList<EntityData> entityData) {
    mContext = context;
    mInflater = LayoutInflater.from(context);
    mEntityDataList = entityData;
  }

  @Override public int getCount() {
    return mEntityDataList.size();
  }

  @Override public EntityData getItem(int position) {
    return mEntityDataList.get(position);
  }

  @Override public long getItemId(int position) {
    return position;
  }

  private final TfHomeActivity mContext;

  @Override public View getView(final int position, View inView, ViewGroup parent) {
    ViewHolder holder;

    if (inView == null) {
      holder = new ViewHolder();
      inView = mInflater.inflate(R.layout.trending_item_mod, null);
      holder.showName = (TextView) inView.findViewById(R.id.show_name);
      // holder.thumbnail = (ImageViewWithLoader) inView.findViewById(R.id.thumbnail);

      inView.setTag(holder);
    } else {
      holder = (ViewHolder) inView.getTag();
    }

    // reset some stuff
    // holder.thumbnail.getImageView().setImageBitmap(null);

    // holder.showName.setText(getItem(position).entityDataItem.getTitle());

    // deal with thumbnails
    String thumbnailUrl = getItem(position).entityDataItem.getTrendingThumbnail();
    // mContext.sendImgDownloadRequest(thumbnailUrl, holder.thumbnail.getImageView(), R.drawable.tunerfish_details_logo2);

    return inView;
  }
}

所以,这个问题可能看起来很长,但我想包含尽可能多的信息。我发现了一个可能相关的 ListView 问题 列表视图中存在大量垃圾收集但不幸的是它似乎不适用于 GridViews。

此外,似乎我并不孤单地遇到这个问题 - 我的一位朋友联系我,询问他的应用程序中完全相同的问题,完全独立。

我的测试设备是运行 CM 7.1 的 OG Droid 和运行 Stock Gingerbread 的 Epic 4G Touch。

那么这是一个框架错误吗?我做错了什么吗?我是否没有包含某个参数?

谢谢。

I have been looking at this for a long time and finally decided to post - my 2xN GridView, which consists of cells with a single image and piece of text is very choppy a lot of times (but sometimes perfectly smooth). Upon examining logcat output, I see things like this once I start scrolling (there are only 12 items in the list):

10-25 17:28:40.420: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed 6K, 47% free 3383K/6279K, external 2044K/2161K, paused 38ms
10-25 17:28:40.510: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 36ms
10-25 17:28:40.600: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 40ms
10-25 17:28:41.805: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed 1K, 47% free 3383K/6279K, external 2044K/2161K, paused 34ms
10-25 17:28:41.840: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 25ms
10-25 17:28:41.880: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 25ms
10-25 17:28:41.910: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 20ms
10-25 17:28:41.940: D/dalvikvm(12159): GC_EXTERNAL_ALLOC freed <1K, 47% free 3383K/6279K, external 2044K/2161K, paused 18ms

This was only a single flick to the bottom of the list and back up. Very choppy. If I keep scrolling up and down, the GC keeps going for maybe 5-6 scrolls, then stops. But as soon as I press Menu which brings up a 2-entry menu or switch activities and come back, GC comes back too.

I turned off bitmap assignments for the image - same problem. My cells are essentially empty, yet GC still happens.

I contacted Romain Guy who said I should try allocation tracking. I ran tracking and flicked, but saw no allocation in my own code. I did see allocations followed by calls to
com.android.internal.os.BinderInternal$GcWatcher allocated in finalize, which matches the number of GC lines in logcat. Here is the whole Allocation Tracker dump (or as a picture which is easier to parse):

1   24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
2   12  java.lang.Integer   5   java.lang.Integer   valueOf 
3   24  byte[]  5   dalvik.system.NativeStart   run 
4   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
5   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
6   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
7   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
8   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
9   20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
10  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
11  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
12  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
13  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
14  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
15  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
16  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
17  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
18  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
19  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
20  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
21  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
22  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
23  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
24  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
25  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
26  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
27  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
28  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
29  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
30  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
31  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
32  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
33  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
34  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
35  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
36  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
37  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
38  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
39  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
40  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
41  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
42  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
43  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
44  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
45  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
46  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
47  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
48  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
49  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
50  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
51  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
52  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
53  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
54  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
55  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
56  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
57  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
58  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
59  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
60  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
61  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
62  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
63  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
64  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
65  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
66  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
67  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
68  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
69  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
70  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
71  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
72  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
73  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
74  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
75  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
76  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
77  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
78  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
79  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
80  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
81  8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
82  24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
83  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
84  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
85  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
86  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
87  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
88  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
89  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
90  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
91  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
92  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
93  20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
94  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
95  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
96  8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
97  24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
98  24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
99  36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
100 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
101 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
102 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
103 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
104 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
105 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
106 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
107 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
108 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
109 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
110 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
111 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
112 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
113 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
114 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
115 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
116 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
117 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
118 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
119 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
120 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
121 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
122 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
123 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
124 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
125 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
126 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
127 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
128 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
129 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
130 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
131 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
132 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
133 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
134 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
135 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
136 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
137 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
138 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
139 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
140 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
141 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
142 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
143 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
144 20  java.util.ArrayList 19  android.os.MessageQueue <init>  
145 36  android.os.MessageQueue 19  android.os.Looper   <init>  
146 24  android.os.Looper   19  android.os.Looper   prepare 
147 144 java.lang.Object[]  19  java.lang.ThreadLocal$Values    initializeTable 
148 32  java.lang.ThreadLocal$Values    19  java.lang.ThreadLocal   initializeValues    
149 16  java.lang.VMThread  1   java.lang.VMThread  create  
150 40  java.util.WeakHashMap$Entry 1   java.util.WeakHashMap   put 
151 16  java.security.ProtectionDomain[]    1   java.security.AccessControlContext  <init>  
152 20  java.security.AccessControlContext  1   java.security.AccessController  getContext  
153 16  java.security.ProtectionDomain[]    1   java.security.AccessController  getStackDomains 
154 24  java.lang.String    1   java.lang.AbstractStringBuilder toString    
155 48  char[]  1   java.lang.AbstractStringBuilder <init>  
156 20  java.lang.StringBuilder 1   java.lang.Thread    create  
157 16  android.view.ViewRoot$2 1   android.view.ViewRoot   handleLongPress 
158 80  java.lang.Thread    1   android.view.ViewRoot   handleLongPress 
159 60  com.carrieriq.iqagent.client.metrics.ui.UI11    1   android.view.ViewRoot   submitPointerMetrics    
160 24  org.apache.harmony.dalvik.ddmc.Chunk    5   android.ddm.DdmHandleHeap   handleREAQ  
161 17  byte[]  5   android.ddm.DdmHandleHeap   handleREAQ  
162 24  org.apache.harmony.dalvik.ddmc.Chunk    5   org.apache.harmony.dalvik.ddmc.DdmServer    dispatch    
163 12  java.lang.Integer   5   java.lang.Integer   valueOf 
164 24  byte[]  5   dalvik.system.NativeStart   run 

As you can see, the events directly preceding GC and happening in between every GC, are pretty much as follows:

107 20  java.util.concurrent.CopyOnWriteArrayList$ListIteratorImpl  1   java.util.concurrent.CopyOnWriteArrayList   iterator    
108 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
109 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
110 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
111 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
112 24  java.lang.ref.SoftReference 1   android.view.View   buildDrawingCache   
113 36  android.graphics.Bitmap 1   android.graphics.Bitmap nativeCreate    
114 8   com.android.internal.os.BinderInternal$GcWatcher    2   com.android.internal.os.BinderInternal$GcWatcher    finalize    
115 24  java.lang.ref.WeakReference 2   com.android.internal.os.BinderInternal$GcWatcher    finalize    

I really wish the allocation tracker let me export the whole dump with individual stack traces, but it doesn't, so I'll paste a few stack traces here, most of which have to do with drawing:

android.graphics.Bitmap:

android.graphics.Bitmap nativeCreate    Bitmap.java -2  true    
android.graphics.Bitmap createBitmap    Bitmap.java 477 false   
android.view.View   buildDrawingCache   View.java   6716    false   
android.view.View   getDrawingCache View.java   6567    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1571    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.widget.AbsListView  dispatchDraw    AbsListView.java    1627    false   
android.widget.GridView dispatchDraw    GridView.java   1943    false   
android.view.View   draw    View.java   7022    false   
android.widget.AbsListView  draw    AbsListView.java    3005    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1646    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.view.View   draw    View.java   7022    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1646    false   
android.view.ViewGroup  dispatchDraw    ViewGroup.java  1373    false   
android.view.ViewGroup  drawChild   ViewGroup.java  1644    false   

java.util.concurrent.CopyOnWriteArrayList:

java.util.concurrent.CopyOnWriteArrayList   iterator    CopyOnWriteArrayList.java   332 false   
android.view.ViewTreeObserver   dispatchOnPreDraw   ViewTreeObserver.java   570 false   
android.view.ViewRoot   performTraversals   ViewRoot.java   1293    false   
android.view.ViewRoot   handleMessage   ViewRoot.java   1899    false   
android.os.Handler  dispatchMessage Handler.java    99  false   
android.os.Looper   loop    Looper.java 130 false   
android.app.ActivityThread  main    ActivityThread.java 3691    false   
java.lang.reflect.Method    invokeNative    Method.java -2  true    
java.lang.reflect.Method    invoke  Method.java 507 false   
com.android.internal.os.ZygoteInit$MethodAndArgsCaller  run ZygoteInit.java 907 false   
com.android.internal.os.ZygoteInit  main    ZygoteInit.java 665 false   
dalvik.system.NativeStart   main    NativeStart.java    -2  true    

Here is my GridView container XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <LinearLayout
    android:id="@+id/scroll_items_holder"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:background="@drawable/app_bg"
    android:orientation="vertical" >
    <LinearLayout
      android:id="@+id/buttonsLayout"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center" >
    </LinearLayout>
    <GridView
      android:id="@+id/gridview"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:columnWidth="150dp"
      android:gravity="right"
      android:horizontalSpacing="0dp"
      android:listSelector="@null"
      android:numColumns="auto_fit"
      android:paddingLeft="5dp"
      android:paddingRight="5dp"
      android:stretchMode="columnWidth"
      android:verticalSpacing="10dp" />
  </LinearLayout>
  <include layout="@layout/menu_bar_inc" />
</LinearLayout>

XML file for each GridView cell:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/card"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" >
  <ImageView
    android:id="@+id/thumbnail"
    android:layout_width="fill_parent"
    android:layout_height="120dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="5dp"
    android:scaleType="centerCrop" />
  <TextView
    android:id="@+id/show_name"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:ellipsize="marquee"
    android:maxLines="1"
    android:textColor="@color/white"
    android:textStyle="bold" />
</LinearLayout>

Adapter, most of which is commented out:

package com.tunerfish.tunerfish.adapters;

import java.util.ArrayList;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.tunerfish.tunerfish.core.TfHomeActivity;
import com.tunerfish.tunerfish.databasemanager.dataitem.EntityDataItem;
import com.tunerfish.tunerfish.ui.R;

public class TrendingGalleryAdapter extends BaseAdapter {

  // structure for dumb view holders
  public static class ViewHolder {
    public TextView showName;
    // public ImageViewWithLoader thumbnail;
  }

  // structure for actual data behind the ListView
  public static class EntityData {
    public EntityDataItem entityDataItem;
  }

  public final ArrayList<EntityData> mEntityDataList;

  private final LayoutInflater mInflater;

  public TrendingGalleryAdapter(TfHomeActivity context, ArrayList<EntityData> entityData) {
    mContext = context;
    mInflater = LayoutInflater.from(context);
    mEntityDataList = entityData;
  }

  @Override public int getCount() {
    return mEntityDataList.size();
  }

  @Override public EntityData getItem(int position) {
    return mEntityDataList.get(position);
  }

  @Override public long getItemId(int position) {
    return position;
  }

  private final TfHomeActivity mContext;

  @Override public View getView(final int position, View inView, ViewGroup parent) {
    ViewHolder holder;

    if (inView == null) {
      holder = new ViewHolder();
      inView = mInflater.inflate(R.layout.trending_item_mod, null);
      holder.showName = (TextView) inView.findViewById(R.id.show_name);
      // holder.thumbnail = (ImageViewWithLoader) inView.findViewById(R.id.thumbnail);

      inView.setTag(holder);
    } else {
      holder = (ViewHolder) inView.getTag();
    }

    // reset some stuff
    // holder.thumbnail.getImageView().setImageBitmap(null);

    // holder.showName.setText(getItem(position).entityDataItem.getTitle());

    // deal with thumbnails
    String thumbnailUrl = getItem(position).entityDataItem.getTrendingThumbnail();
    // mContext.sendImgDownloadRequest(thumbnailUrl, holder.thumbnail.getImageView(), R.drawable.tunerfish_details_logo2);

    return inView;
  }
}

So, this question may look long, but I wanted to include as much info as possible. I found a possibly related ListView issue Lots of garbage collection in a listview but unfortunately it doesn't seem to apply to GridViews.

Additionally, it doesn't seem like I'm alone with this problem - a friend of mine contacted me to ask about exactly the same issue in his app, completely independently.

My test devices are OG Droid running CM 7.1 and Epic 4G Touch running stock Gingerbread.

So is this a framework bug? Am I doing something wrong? Am I not including a certain parameter?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

峩卟喜欢 2024-12-19 02:42:08

在随机尝试了更多的事情之后,我相信我能够通过在 XML 中将 GridView 的 scrollingCache 设置为 false 来解决该问题。现在已经变得光滑如黄油了。

http://developer.android.com/reference/android/widget /AbsListView.html#attr_android:scrollingCache

因此,本应使 GridView 使用更多内存并更快地从缓存中绘制的设置实际上会由于 GC 而导致相反的结果:它波涛汹涌。关闭缓存会使用更少的内存,并且不再不稳定。

这在我的书中是双赢的,我希望它对未来的人有所帮助(ಠ_ಠ Google)。

编辑:刚刚在性能良好的ListView上尝试过,它偶尔会调用GC_EXTERNAL_ALLOC来释放少量内存。从 ListView 中删除它完全消除了许多微小的 GC_EXTERNAL_ALLOC 调用,只留下了偶尔较大的 GC_CONCURRENT 调用。现在,性能良好的 ListView 就是性能出色的 ListView。因此,scrollingCache 似乎是任何列表中都应该避免的东西,并且在我看来,默认情况下不应启用它。

After trying out more things at random, I believe I was able to solve the issue by setting GridView's scrollingCache to false in the XML. It's now buttery smooth.

http://developer.android.com/reference/android/widget/AbsListView.html#attr_android:scrollingCache

So, a setting that is supposed to make the GridView use more memory and draw from cache faster in fact causes just the opposite due to GC by making it choppy. Turning the cache off uses less memory and isn't choppy anymore.

This is a win-win in my book, and I hope it helps someone in the future (ಠ_ಠ Google).

Edit: Just tried it on a decently-performing ListView, which occasionally would call GC_EXTERNAL_ALLOC to free small amounts of memory. Removing it from a ListView got rid of many tiny GC_EXTERNAL_ALLOC calls altogether and only an occasional larger GC_CONCURRENT call is left. Now a decently-performing ListView is a great-performing ListView. So scrollingCache seems to be something to avoid in any list and shouldn't be enabled by default IMO.

桃酥萝莉 2024-12-19 02:42:08

这也是 ListView 的一个问题,频繁的 stop-the-world 垃圾回收会导致最终用户体验不佳,并导致用户将不稳定的 UI 性能归咎于 Android。不过,也可以用同样的方式通过将scrollingCache设置为false来解决这个问题。

This is also a problem with ListViews, and the frequent stop-the-world garbage collection causes a poor end-user experience and leads the user to blame Android for choppy UI performance. However, this problem can also be solved in the same way by setting the scrollingCache to false.

在巴黎塔顶看东京樱花 2024-12-19 02:42:08

使用 SimpleCursorAdapter 和 ListActivity 中使用的自定义 2 行 ListView 布局,没有图像,只有文本,我有 CacheColorHint - #00000000。
在我开始之前,我会说一个快速修复是删除cachecolorhint,但我需要它,所以它不是对GC的修复,所以......

我现在和过去都遇到过同样的问题,但这会引发一个曲线球在其中...我有两个应用程序,它们本质上是彼此的镜像。一个可以运行得很好,logcat 中没有猖獗的垃圾收集,并且滚动很漂亮,另一个则不能很好地工作,没有任何代码复制和粘贴可以将其从一个到另一个修复。

另外!...有时在应用程序中工作得不太好,当我从查询中重新调用列表并为列表视图使用稍微不同的布局时,我可以让它工作。不过,不要急于下结论,因为如果我离开并返回,在自定义 2 行列表项布局上使用简单游标适配器的相同排序查询将再次导致 GC。换句话说,有时它会正常工作,有时却不能。请注意,我将“scrollingCache”保留为两个应用程序的默认设置,正如我所说,它们是彼此的副本。

不久前我遇到了这个问题,并以某种方式解决了它,它与 ScrollingCache 无关。相反,它与我针对某些旧版本的 Android 进行编译有关(我认为),我的记忆不能 100% 确定这一点,但我发誓修复与构建/编译器问题有关。如果我记得是什么修复了它,我会发布一些内容。我使用环绕声,所以我正在寻找变化。
我希望这是有道理的

Using SimpleCursorAdapter with a custom 2 line ListView layout being used in a ListActivity, no images just text and I have CacheColorHint - #00000000.
before I begin I will say that a quick fix is removing cachecolorhint but I need it so it is not a fix to the GC so....

I have had issues with this same problem now and in the past however this throws a curve ball in it... I have two applications which are essentially mirror images of each other. One will run just fine with no rampant Garbage Collection in the logcat and it scrolls beautifully, The other does not work so well and nothing, no copy and pasting of code can fix it from one to the other.

ALSO!...Sometimes in the app that is not working so well, I can get it to work when I resort the list from a query and use a slightly different layout for the list view. Don't jump to conclusions though because if I navigate away and come back, the same sorted query using simple cursor adapter on a custom 2 line list item layout will cause the GC again. In other words sometimes it will simply work correctly, and other times it won't. Mind you, I have "scrollingCache" left as the default on both apps and as I said they are copies of each other.

A while back I encountered this and was able to resolve it somehow and it had nothing to do with ScrollingCache. Rather it had to do with my build compiling against some old version of Android (I think) My memory is not 100% certain of this but I swear the fix was related to a build/compiler issue. I will post something if I remember what fixed it. I use Surround so I am searching for changes.
I hope this made sense

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文