Cómo evitar la renovación de las celdas al llamar a notifyDataSetChanged () para PinterestLikeAdapterView?

Fondo

Estoy usando la biblioteca PinterestLikeAdapterView para mostrar algunas imágenes de Internet, que es como un gridView pero con diferentes alturas para cada celda.

El problema

Desde que uso esta biblioteca para mostrar imágenes de Internet, es crucial que al llamar a notifyDatasetChanged no causará un lío en las vistas.

Por alguna razón, llamar a esta función llamaría al método getView () con diferentes posiciones para las vistas. Por ejemplo, aunque no hice scroll en absoluto, y llamar a notifyDatasetChanged (o addAll en caso de que sea un ArrayAdapter), para la posición 0 tomará lo que era la vista de la posición 8, para la posición 1 tomará la vista de la posición 7, y así sucesivamente …

Esto hace que toda la cuadrícula actualice sus imágenes, por lo que arruina el UX.

Normalmente, en gridView y listView, la forma de superar la actualización es colocar la posición que se utilizó para la vista dentro de la vistaHolder, y si son iguales, significa que todavía coinciden.

por ejemplo:

... getView(...) { //<=inflate a new view if needed //avoid refreshing view in case it's still the same position: if(position==holder.position) return rootView; holder.position=position; //<=update the view according to its data ... } 

Sin embargo, aquí se reutilizan otras vistas en un orden diferente, por lo que este truco no funcionará aquí.

Debido a este problema, no sólo recibo actualizaciones de casi todas las vistas visibles, pero desde que uso la biblioteca de DiskCacheLru , se bloquea ya que intenta poner 2 datos idénticos inputSteam en la misma clave utilizando 2 subprocesos.

La pregunta

¿Que puedo hacer? ¿Es un error conocido en la biblioteca?

Tal vez estoy usando una mala manera de superar refrescos?

Por ahora, uso caché de memoria al menos para obtener elementos que se almacenaron en caché antes, pero eso es más como una "cura" que una "vacuna" …

    4 Solutions collect form web for “Cómo evitar la renovación de las celdas al llamar a notifyDataSetChanged () para PinterestLikeAdapterView?”

    Respuesta corta :

    Utilice una biblioteca de carga de imágenes como Picasso que almacena en caché las imágenes más usadas en la memoria, por lo que no es necesario recargarlas desde la red.

    Respuesta larga:

    AdapterView hace algo llamado View reciclado, donde las Views que ya no son necesarias para mostrar una posición se reutilizan para mostrar otra. (Por ejemplo, a medida que se desplaza hacia abajo, las Views que desaparecen en la parte superior de la pantalla se reutilizan para nuevas posiciones en la parte inferior de la pantalla.) Debido a esto, es normal que getView() pase la misma View durante más de Una posición.

    Esto se hace por razones de rendimiento: Inflar nuevas Views es difícil y lleva tiempo, por lo que AdapterView intenta hacerlo tan poco frecuentemente como sea posible.

    Cuando se utiliza un soporte, se almacenan referencias a los niños ImageView y TextView dentro de la View del elemento, por lo que no es necesario buscarlos con findViewById() cada vez, normalmente no se almacena nada específico en una posición determinada porque View y su titular a menudo se utilizan para diferentes posiciones.

    Ahora, cuando llama a notifyDataSetChanged() , AdapterView asume que el conjunto de datos ha cambiado por completo. La imagen que estaba asociada con la posición 8 ya no puede estar presente, o puede estar asociada ahora con la posición 12. En consecuencia, todas las Views existentes se AdapterView , pero debido a que AdapterView todavía desea evitar inflar nuevas Views , se vuelven a utilizar para mostrar los nuevos datos, sin tener en cuenta la posición que estaban mostrando anteriormente.

    Esto explica por qué getView() se está pasando la misma View para diferentes posiciones y por qué las posiciones visibles se están actualizando cuando se llama a notifyDataSetChanged() . Pero, ¿cómo evitar que tus imágenes se actualicen, arruinando la experiencia del usuario?

    Utilice una biblioteca de carga de imágenes como Picasso que almacena en caché las imágenes más usadas en la memoria, por lo que no es necesario recargarlas desde la red. La actualización continuará ocurriendo, pero será instantánea.

    View getView(int position, View view, ViewGroup parent) siempre se llamará ascendente, después de notifyDataSetChanged() .
    Supongo que, el orden de terminar la tarea de descarga causará este problema.
    Como mencionó en su pregunta, mantener la posición es una buena manera de evitar este problema.

    Aquí hay otra manera de resolverlo, también reutilizar las vistas de imagen.

    Mantenga una referencia débil de cada ImageView en la tarea de descarga.
    A continuación, envuelva la tarea de descarga en un dummy ColorDrawable .
    Cuando se llama a getView , establezca el dummy ColorDrawable en ImageView e inicie la descarga. Cuando se haya completado la descarga, vuelva a establecer la imagen descargada en ImageView en OnPostExecute() .

    Explicación
    http://android-developers.blogspot.jp/2010/07/multithreading-for-performance.html
    Código fuente
    https://code.google.com/p/android-imagedownloader/source/checkout

    Hay un muy buen ejemplo en PinterestLikeListView en GitHub

    Aquí está la biblioteca StaggeredGridView

    Una versión modificada de StaggeredGridView experimental de Android. Incluye OnItemClickListener propio y OnItemLongClickListener, selector y restauración de posición fija.

    Usted puede conseguir el proyecto de la biblioteca aquí biblioteca

    Y usted puede conseguir el proyecto de demostración aquí

    Esto es muy bueno proyecto de código abierto, por lo que puede utilizar en lugar de PinterestLikeAdapterView

    Introduzca aquí la descripción de la imagen

    Espero que esta biblioteca te ayude.

    Parece que los autores de esta biblioteca lo han arreglado, después de algún tiempo he informado sobre ello:

    https://github.com/huewu/PinterestLikeAdapterView/issues/8

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.