Android: profundicemos en DiffUtil | Autor: Areyana | Junio de 2021
Cualquiera que haya encontrado desarrollo en la plataforma Android pronto se encontrará con la tarea de implementar una visualización de lista, como una lista de productos en una aplicación de tienda. El widget más común para esta tarea es RecyclerView.
Hasta finales de 2016, los programadores llaman a métodos para mostrar dónde y cómo se modifican los datos de sus listas, o actualizar la lista completa, lo que no siempre es una solución eficaz. Algunos ejemplos de tales métodos:
- adapter.notifyItemRangeInserted (rangeStart, rangeEnd);
- adapter.notifyItemRemoved (posición);
- adapter.notifyItemChanged (posición);
- adapter.notifyItemInserted (posición);
- Adapter.notifyDataSetChanged ();
- adapter.notifyItemMoved (fromPosition, toPosition);
Para reemplazar este método convencional e inconveniente, Google ha lanzado una actualización a la biblioteca de soporte y agregó DiffUtil.
diferenciaFUtilidad Es una clase auxiliar que ayuda a calcular la diferencia entre dos listas y generar una lista de operaciones para convertir la primera lista en la segunda lista.Comenzó a usarse para actualizar Vista de reciclador adaptador.
En la mayoría de los casos, nuestra lista cambia por completo, la reemplazamos en el adaptador y luego llamamos Notifique que el conjunto de datos ha cambiado, Este método es muy pesado para el procesamiento del sistema. DiffUtil Este problema está resuelto (aunque en parte, a veces es más rentable llamar a notificar manualmente, por ejemplo, si no tenemos el costo adicional para calcular la ubicación de la ubicación del artículo cambiado).
DiffUtil.Callback Es una clase abstracta con 4 métodos abstractos y 1 método no abstracto.
- getOldListSize (): Devuelve el tamaño de la lista anterior.
- getNewListSize (): Devuelve el tamaño de la nueva lista.
- areItemsTheSame (int oldItemPosition, int newItemPosition): Llamada para determinar si los objetos representan el mismo modelo. Por ejemplo, si hay un ID en el modelo, verifique los ID de los modelos en las dos listas aquí.
- areContentsTheSame (int oldItem Position, int newItemPosition): Se llama cuando areItemsTheSame devuelve True. Compruebe si el modelo es el mismo en términos de datos (la lógica puede cambiar según los requisitos de la interfaz de usuario).
- getChangePayload (int antigua ubicación del proyecto, int nueva ubicación del proyecto): Si areItemTheSame devuelve verdadero y areContentsTheSame devuelve falso, DiffUtil llama a este método para obtener información adicional sobre el cambio.A veces debe tenerse en cuenta que si solo se devuelve aquí un campo modificado, entonces Animador de proyectos Se animará correctamente y no se volverá a dibujar la celda completa.
¡Entonces todo es simple!usar Calcule la diferencia,tenemos Resultado de diferencia Y llama al método de resultado dispathUpdatesToAplicamos los cambios al adaptador. Resultado de diferencia Es una serie de operaciones simples de eliminar / cambiar / agregar / mover descritas al principio del artículo. Hay otra pregunta, cómo obtuvo esta secuencia, y la complejidad de su algoritmo también es muy interesante. Esto es lo que consideraremos más adelante en el artículo.
DiffUtil Utilice el algoritmo de Myers por sí solo. El algoritmo determina la presencia / ausencia de cambios, pero no encuentra la capacidad de mover elementos. y entonces, DiffUtil Utilice los resultados del algoritmo de Myers para buscar además movimiento. Cuando no se encuentra ningún desplazamiento, la complejidad del algoritmo es O (N + D²), en el caso contrario es O (N + D²) + O (P²), donde P es el número de elementos agregados y eliminados.
Tomemos como ejemplo el trabajo del algoritmo de Myers. Tomemos dos secuencias.
Q1 = CAABC
Q2 = Baka
Construyamos una matriz usando estas dos secuencias y numeremos cada fila comenzando desde 0.
En la intersección con la misma letra, trazaremos una línea diagonal. Trataremos estos cuadrados como «especiales». Siguiéndolos en cada paso, el algoritmo «cae» más a través de esta línea diagonal y no considera esta acción como un movimiento.
Luego, iteraremos a través de diferentes rutas hasta que un método alcance el punto final (5, 5) más rápido que el otro.
En este ejemplo, hay 2 soluciones igualmente correctas. Ahora, con esta solución, puede escribir una serie de diferencias y seguir estas reglas:
- Se considera que cada movimiento vertical agrega el elemento correspondiente al cuadrado al que nos movimos de la «nueva» fila (Q2). Por ejemplo, una transición de (0,0) a (0,1) significa que se agrega «B» de Q2.
- Se considera que cada movimiento horizontal elimina el símbolo correspondiente del cuadrado al que nos movimos desde la línea «antigua» (Q1). Por ejemplo: de (2,5) a (3,5) significa eliminar «A» de la cadena Q1.
- Cada movimiento en diagonal se considera una reserva del símbolo correspondiente en el cuadrado al que nos movimos.
Para cada ruta correcta, escribiremos la secuencia:
Orden inferior:
- (0, 0) -> (0, 1) + B
- (0, 1) -> (0, 2) + A
- (0, 2) -> (1, 3) C
- (1, 3) -> (1, 4) + C
- (1, 4) -> (2, 5) A
- (2, 5) -> (3, 5) -A
- (3, 5) -> (4, 5) -B
- (4, 5) -> (5, 5) -C
Orden superior:
- (0, 0) -> (1, 0) -C
- (1, 0) -> (2, 0) -A
- (2, 0) -> (2, 1) + B
- (2, 1) -> (3, 2) A
- (3, 2) -> (4, 2) -B
- (4, 2) -> (5, 3) C
- (5, 3) -> (5, 4) + C
- (5, 4) -> (5, 5) + A
Como puede ver, cada secuencia contiene el mismo número de eliminaciones, adiciones y guardados. Como resultado, ambas secuencias son soluciones correctas al problema original y recibimos un conjunto de acciones para transformar la secuencia original en una nueva secuencia.en DiffUtil, El algoritmo de Myers se utiliza para buscar areItemsTheSame () Método, más una vez más, establece el estado de cada objeto en función de la solución y luego decide qué método de notificación inicial debe usar el adaptador para un objeto específico.