android - que - tesis sobre contaminacion por residuos solidos
Gran cantidad de recolección de basura en una lista (9)
De hecho revisé tu código y lo pirateé un poco para que funcione en mis dispositivos. Puedo confirmar que su ListAdapter está bien y que el problema está en otra parte.
Esto es lo que haces en el método createDefaultLabelsList ().
mItemsInList.clear();
ItemInRootList item;
do {
item = new ItemInRootList();
item.isLabel = true;
item.id = c.getString(c.getColumnIndex(Labels.KEY_ID));
item.title = Labels.label(item.id);
//TODO: fix this label.label = c.getString(c.getColumnIndex(Labels.KEY_LABEL));
item.unreadCount = c.getString(c.getColumnIndex(Labels.KEY_UNREAD_COUNT));
mItemsInList.add(item);
} while (c.moveToNext());
Parece que no usar una variable local en tu ciclo es la causa de tu problema de rendimiento, lo creas o no. Reemplace eso con:
mItemsInList.clear();
do {
ItemInRootList item = new ItemInRootList();
item.isLabel = true;
item.id = c.getString(c.getColumnIndex(Labels.KEY_ID));
item.title = Labels.label(item.id);
//TODO: fix this label.label = c.getString(c.getColumnIndex(Labels.KEY_LABEL));
item.unreadCount = c.getString(c.getColumnIndex(Labels.KEY_UNREAD_COUNT));
mItemsInList.add(item);
} while (c.moveToNext());
¡y disfruta de tu ardiente lista rápida! Esto me lo resolvió en htc hero (2.1) y Xoom (3.1) usando una ListActivity.
Así es como lo habría hecho, en primer lugar, pero no estoy exactamente seguro de cómo esto explica el comportamiento lento con su implementación original.
Descubrí esto porque para reproducir tu problema tuve que reemplazar la forma en que construiste la lista, simplemente creé una lista con 10k etiquetas aleatorias y la vi desplazarse muy rápido. Luego me di cuenta de que no usamos exactamente el mismo bucle, usted estaba agregando la misma referencia una y otra vez mientras agregaba 10k referencias diferentes. Cambié a su implementación y reproduje el error.
Tengo un ListView que usa un adaptador personalizado. GetView del adaptador personalizado usa todas las prácticas recomendadas:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SuscriptionsViewsHolder holder;
ItemInRootList item = mItemsInList.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.label, null);
holder = new SuscriptionsViewsHolder();
holder.label = (TextView) convertView.findViewById(R.id.label_label);
holder.icon = (ImageView) convertView.findViewById(R.id.label_icon);
convertView.setTag(holder);
} else {
holder = (SuscriptionsViewsHolder) convertView.getTag();
}
String text = String.format("%1$s (%2$s)", item.title, item.unreadCount);
holder.label.setText(text);
holder.icon.setImageResource(item.isLabel ? R.drawable.folder : R.drawable.file );
return convertView;
}
Sin embargo, cuando me desplazo, es lento debido a la gran recolección de basura:
GC_EXTERNAL_ALLOC freed 87K, 48% free 2873K/5447K, external 516K/519K, paused 30ms
GC_EXTERNAL_ALLOC freed 7K, 48% free 2866K/5447K, external 1056K/1208K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2866K/5447K, external 1416K/1568K, paused 28ms
GC_EXTERNAL_ALLOC freed 5K, 48% free 2865K/5447K, external 1600K/1748K, paused 27ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2865K/5447K, external 1780K/1932K, paused 30ms
GC_EXTERNAL_ALLOC freed 2K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed 2K, 48% free 2870K/5447K, external 1780K/1932K, paused 25ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed 3K, 48% free 2870K/5447K, external 1780K/1932K, paused 25ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2871K/5447K, external 1780K/1932K, paused 28ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2871K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 27ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 29ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 26ms
GC_EXTERNAL_ALLOC freed <1K, 48% free 2870K/5447K, external 1780K/1932K, paused 34ms
Lo que parece estar mal?
EDITAR @ 12: 47 GMT:
De hecho, es un poco más complicado que esto. La interfaz de usuario de mi aplicación se basa en 2 partes. Uno es el cerebro de una pantalla, creando las vistas, manejando la entrada del usuario, etc. El otro es un Fragment
si el dispositivo tiene Android 3.0, de lo contrario es una Activity
.
El GC ocurrió en mi dispositivo Nexus One 2.3.3, por lo que usé la Activity
. No tengo mi Xoom conmigo para probar el comportamiento con un Fragment
.
Podría publicar la fuente si es necesario, pero déjame intentar explicarlo:
-
RootList
es el cerebro de la interfaz de usuario. Contiene :- a
List<>
de elementos que se colocarán enListView
. - un método que construye esta lista desde un SQLite db
- un BaseAdapter personalizado que contiene básicamente solo el método getView pegado arriba
- a
-
RootListActivity
es unaListActivity
, que:- usa un diseño XML
- el diseño tiene, por supuesto, una vista de lista con id
android.id.list
- las devoluciones de llamadas de
Activity
se envían a la claseRootList
utilizando una instancia de RootList creada cuando se crea la actividad (constructor, noonCreate
) - en
onCreate
, llamo a los métodos deRootList
que crearán la lista de elementos, y establecer los datos de la lista a una nueva instancia de mi clase personalizada derivada deBaseAdapter
EDITAR el 17 de mayo a las 9:36 PM GMT:
Aquí está el código de la actividad y la clase que hace las cosas. http://pastebin.com/EgHKRr4r
Debería usar DDMS y su Rastreador de asignación para averiguar exactamente qué está generando tantos objetos. Sin embargo, tenga en cuenta que String.format () es muy conocido por generar grandes cantidades de basura.
http://developer.android.com/resources/articles/track-mem.html
Encontré el problema. Mi diseño XML para la actividad fue:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include android:id="@+id/rootlist_header" layout="@layout/pre_honeycomb_action_bar" />
<ListView android:id="@android:id/list"
android:layout_below="@id/rootlist_header"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:textColor="#444444"
android:divider="@drawable/list_divider"
android:dividerHeight="1px"
android:cacheColorHint="#00000000" />
</RelativeLayout>
Si android:cacheColorHint="#00000000"
el android:cacheColorHint="#00000000"
, el pesado GC está fuera y el desplazamiento es suave . :)
Realmente no sé por qué se estableció este parámetro, porque no lo necesito. Tal vez copié demasiado en lugar de construir mi diseño XML.
GRACIAS por su apoyo, realmente aprecio su ayuda.
Esto comienza con 4.4.4 Actualización de KitKat. Vuelva a ejecutar el código que ya tiene el código normal y aparece este problema. ListView es completamente inutilizable ahora debido a un desplazamiento muy lento. (Nexus 4)
Y no estoy usando ningún formateador en él.
Cuando la Vista se está desplazando, aparece un gran número de mensajes de GC.
String text = String.format ("% 1 $ s (% 2 $ s)", item.title, item.unreadCount); Puede ser String.format () crea muchas cadenas intermedias que contaminan el GC. Pruebe StringBuilder e intente almacenar en caché la cadena que crea. También como @tmho dijo try holder.icon.setImageDrawable (); en lugar de holder.icon.setImageResource (); porque setImageResource () crea un objeto Drawable cada vez. Y cada Drawable tiene aproximadamente 50-60 bytes. Parece que el mapa de bits heave no está duplicado en este caso, solo contenedor dibujable, pero puede ser suficiente para provocar llamadas GC periódicas.
También tuve un problema con el android:cacheColorHint="#00000000"
. Necesitaba usarlo, aunque porque tengo una imagen de fondo fija.
Descubrí que la configuración de las siguientes propiedades deshabilita el almacenamiento en caché de la vista de lista de Android y la lista se desplaza sin problemas (ya no se llama al GC tan a menudo):
android:scrollingCache="false"
android:animationCache="false"
Además, si desea deshacerse del color de selección predeterminado, use esto:
android:listSelector="#00000000"
Tengo una pregunta similar, mi lista de listas mostrará imágenes de Internet y las guardará en una tarjeta SD. Cuando se inicie la aplicación más tarde, se usará la imagen local, luego, cuando recorra la vista de lista, aparecerán muchos GC en el logcat y la vista se aturdirá un poco.
Noté que cuando la aplicación se lanzó por primera vez, con imágenes todas de Internet, la vista de lista se muestra normalmente.
Por cierto, utilicé el android-imagedownloader de http://code.google.com/p/android-imagedownloader/ y agregué un código de caché de archivo local.
Así que aquí está mi solución, cuando carga la imagen del archivo local, agregaré el objeto de mapa de bits a la memoria caché (un HashMap estático), después de eso, cuando la vista de lista se desplace hacia arriba y hacia abajo, obtendrá la imagen de la memoria caché y mucho GC no volvió a suceder.
esta
String text = String.format("%1$s (%2$s)", item.title, item.unreadCount);
hará que el GC se llame muchas veces.
String.format()
asigna memoria temporal además de la cadena que finalmente produce.
otra forma de hacer esto.
usando la clase StringBuilder
, así.
StringBuilder builder = new StringBuilder(128);
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SuscriptionsViewsHolder holder;
ItemInRootList item = mItemsInList.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.label, null);
holder = new SuscriptionsViewsHolder();
holder.label = (TextView) convertView.findViewById(R.id.label_label);
holder.icon = (ImageView) convertView.findViewById(R.id.label_icon);
convertView.setTag(holder);
} else {
holder = (SuscriptionsViewsHolder) convertView.getTag();
}
String text = String.format("%1$s (%2$s)", item.title, item.unreadCount);
builder.setLength(0);
builder.append(item.title).append(" (").append(item.unreadCount).append(")");
holder.label.setText(builder.toString());
holder.icon.setImageResource(item.isLabel ? R.drawable.folder : R.drawable.file );
return convertView;
}
intente holder.icon.setImageBitmap();
en lugar de holder.icon.setImageResource();