android - studio - Gallery ImageAdapter convertView siempre es nulo
lista view android (3)
He solucionado esto al usar un caché personalizado como sugiere dskinner.
Precalculo (ancho de pantalla / min ancho de elemento) el máximo de # elementos que se pueden mostrar en la galería en la pantalla a la vez y agrego algunos más (la galería necesitará más elementos para mostrar a la izquierda y a la derecha a medida que desplazarse por ella). Creo una matriz de este tamaño: las vistas se crean según lo solicitado y se colocan en la caché. Utilice la posición% de tamaño de caché para determinar qué vista en caché devolver cuando se llama a getView.
Estoy utilizando una Galería con un ImageAdapter para cargarlo con ImageViews que extraen imágenes de mis recursos. Mi problema es que el convertView que se pasa al método getView () en mi adaptador siempre es nulo. Esto significa que se crea un nuevo ImageView cada vez que se llama a getView (). Esto conduce a un rendimiento horrible porque el GC se ejecuta constantemente para eliminar todos estos ImageView creados y que ya no se usan.
Aparentemente, se trata de un error conocido: la memoria caché de la vista de la galería está rota; nunca convierte vistas .
Mis dos soluciones preferidas son: 1. manejar un caché de vistas en el adaptador y ocuparse de toda la lógica necesaria para volver a utilizarlas correctamente. o 2. incluir una copia del widget de la Galería e intentar solucionarlo para que devuelva las vistas recicladas de forma adecuada.
Empecé a implementar la opción uno, pero pronto me doy cuenta de que no sé exactamente cómo hacer toda la lógica detrás de esa operación. Estoy empezando a pensar que la opción dos podría ser más fácil.
Encontré el código para el widget de la Galería aquí: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/widget/Gallery.java
No lo entiendo del todo, pero puedo ver que está llamando
child = mAdapter.getView(position, null, this);
en la línea 745. Mi (disparo en la oscuridad) adivina que esta es la raíz del problema.
¿Alguien tiene experiencia con este error? ¿O puede alguien señalarme en la dirección correcta para averiguar cómo funciona la situación del reciclador para que pueda ajustar este widget para que funcione correctamente? O incluso sugerir alguna opción alternativa que pueda estar pasando por alto.
EDITAR: La mejor solución que he encontrado fue una implementación llamada EcoGallery. El único lugar donde puedo encontrar referencia en línea ya está aquí . Para que funcione, debes colocar cada fragmento en el lugar correcto dentro de tu proyecto.
No tengo experiencia con el widget Galería, pero estoy usando mucho ListView con imágenes. De acuerdo con su problema, y el vínculo al problema de Google, todavía no han solucionado este problema.
Entonces, hay una solución con una buena biblioteca (y ejemplos dentro de ella), que resuelven problemas de caché / ajax, y mucho más.
Enlace a la biblioteca
o, más concretamente, enlaces a ejemplos de imágenes
Si descarga sus ejemplos, encontrará cómo implementaron la galería con el widget Galería, utilizando su clase de utilidad AQuery en
com.androidquery.test.image.ImageLoadingGalleryActivity
class.
Fragmento del código:
final List<Photo> entries;// here only to show what enteries are...
listAq = new AQuery(this); //define as Action class member, here only to show what it is
ArrayAdapter<Photo> aa = new ArrayAdapter<Photo>(this, R.layout.gallery_item, entries){
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getLayoutInflater().inflate(R.layout.gallery_item, parent, false);
}
Photo photo = getItem(position);
AQuery aq = listAq.recycle(convertView);
aq.id(R.id.name).text(photo.title);
String tbUrl = photo.tb;
if(!aq.shouldDelay(position, convertView, parent, tbUrl)){
aq.id(R.id.tb).image(tbUrl);
aq.id(R.id.text).text(photo.title).gone();
}else{
aq.id(R.id.tb).clear();
aq.id(R.id.text).text(photo.title).visible();
}
return convertView;
}
};
aq.id(R.id.gallery).adapter(aa);
Donde la foto es solo un objeto POJO (obtenido desde el control remoto):
class Photo {
String tb;
String url;
String title;
String author;
}
R.id.gallery
refiere a
<Gallery
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="200dip" />
Y R.layout.gallery_item
refiere a:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dip"
android:layout_height="75dip" >
<ProgressBar
android:id="@+id/progress"
android:layout_width="15dip"
android:layout_height="15dip"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/tb"
style="@style/GalleryItem"
android:layout_width="100dip"
android:layout_height="75dip" />
<TextView
android:id="@+id/text"
android:layout_width="100dip"
android:layout_height="75dip"
android:gravity="center"
android:maxLines="4"
android:padding="15dip"
android:text="Dummy TextDummy TextDummy TextDummy TextDummy Text"
android:textColor="#FFFFFFFF"
android:textSize="8sp" />
</RelativeLayout>
Espero que encuentres útil esta biblioteca para resolver tu problema.
No tengo ninguna experiencia con ese error en particular, pero he hecho un caché personalizado antes con un paginador de vista de terceros (antes de la lib de soporte).
Realmente no es muy difícil sinceramente. En mi caso, sabía que habría, como máximo, un elemento en la pantalla. Pero también quería que el elemento a la izquierda y a la derecha fuera precargado (se trataba de webviews que extraían datos de la red). Entonces tengo una matriz simple de 3 vistas.
[V1, V2, V3]
Ahora, lo único que debe hacer es correlacionar una posición en su adaptador con una posición en su caché. Hay una variedad de formas en que puedes abordar esto. La primera vez que lo amplifiqué, simplemente hice que mi vista actual fuera V2 y giré los elementos de la matriz cuando volteé el busca. Así que cambiar a la vista siguiente alteraría mi matriz
[V2, V3, V1]
Fue fácil de seguir. O simplemente puede hacer los cálculos y calcular una posición en una posición relativa de la memoria caché.
Otro enfoque es crear una cola de último en entrar, primero en salir. Recicle las vistas empujándolas a la cola, y cuando necesite una vista, solo saque una de ellas.