Métodos getViewTypeCount y getItemViewType de ArrayAdapter

159

¿Puede alguien en palabras simples explicarme el uso getViewTypeCount()y los getItemViewType()métodos de ArrayAdapter?

Eugene
fuente

Respuestas:

308

Estos manejan el caso donde desea diferentes tipos de vista para diferentes filas. Por ejemplo, en una aplicación de contactos, es posible que desee que las filas pares tengan imágenes en el lado izquierdo y las filas impares tengan imágenes en el derecho. En ese caso, usarías:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

El marco de trabajo utiliza su tipo de vista para decidir qué vistasconvertViewgetView utilizar en su método . En otras palabras, en el ejemplo anterior, sus filas pares solo obtendrán vistas recicladas con imágenes en el lado izquierdo para reutilizar, y las filas impares solo obtendrán aquellas con imágenes a la derecha.

Si cada fila de su lista tiene el mismo diseño, no necesita preocuparse por los tipos de vista. De hecho, BaseAdapter.java proporciona un comportamiento predeterminado para todos los adaptadores:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

De hecho, esto le proporciona el mismo tipo de vista para cada fila.

Editar - para delinear el flujo general:

  1. Vincula los datos a su AdapterViewutilizando un adaptador.
  2. Los AdapterViewintentos para mostrar los elementos que son visibles para el usuario.
  3. El marco requiere getItemViewTypefila n, la fila que está a punto de mostrar.
  4. El marco comprueba su grupo de vistas recicladas para ver las vistas del ntipo de fila . No encuentra ninguna porque aún no se han reciclado las vistas.
  5. getViewse llama para fila n.
  6. Llama getItemViewTypea una fila npara determinar qué tipo de vista debe usar.
  7. Utiliza una instrucción if / switch para inflar un archivo xml diferente según el tipo de vista que se requiera.
  8. Rellena la vista con información.
  9. Devuelve la vista, saliendo getView, y la vista de su fila se muestra al usuario.

Ahora, cuando una vista se recicla desplazándose fuera de la pantalla, pasa a un grupo de vistas recicladas que administra el marco. Estos están esencialmente organizados por tipo de vista para que se le proporcione una vista del tipo correcto en el convertViewparámetro de su getViewmétodo:

  1. El marco vuelve a llamar getItemViewTypea la fila que desea mostrar.
  2. Esta vez, hay una vista en el grupo reciclado del tipo apropiado.
  3. La vista reciclada se le pasa a usted como el convertViewparámetro de su getViewmétodo.
  4. Rellena la vista reciclada con nueva información y la devuelve.
Matthew Willis
fuente
1
@ Matthew, gracias por tu respuesta. ¿Puede describir el flujo cómo se invocan estos métodos? Además, no entiendo cómo esto se asocia realmente con mis datos en res / layout.
Eugene
No hay un contrato explícito para cuando se invocan estos métodos. res / layout es el lugar para ver objetos. Este es un adaptador . Debe verificar el tipo de elemento en su método getView e inflar la vista adecuada desde res / layout en consecuencia.
Matthew Willis
1
Lo está devolviendo usted mismo en getItemViewType.
Matthew Willis
Realiza la asociación manualmente en getView: if (type == 0) {/ * inflate R.layout.row_icon_on_left /} else {/ inflate R.layout.row_icon_on_right * /}
Matthew Willis
75
¡Tener cuidado! getItemViewType () debe devolver un int entre 0 y getViewTypeCount () - 1.
PacificSky
12

Si necesitamos mostrar diferentes tipos de vista en la vista de lista, entonces es bueno usarla getViewTypeCount()y getItemViewType()en el adaptador en lugar de alternar una vista View.GONEy View.VISIBLEpuede ser una tarea muy costosa getView()que afectará el desplazamiento de la lista.

Por favor, compruebe este para el uso de getViewTypeCount()y getItemViewType()en el adaptador.

Enlace: the-use-of-getviewtypecount

kyogs
fuente
Devolver IGNORE_ITEM_VIEW_TYPE en getItemViewType () siempre pasará 'view' como nulo en getView (int position, View view, ViewGroup viewGroup) obligando a inicializar todos los componentes de la interfaz de usuario. No es un mal indicador de rendimiento en el que, en el caso de un patrón de titular, podemos reutilizar las vistas de IU existentes y simplemente podemos alternar la vista a View.GONE o View.VISIBLE según la posición.
Namrata Bagerwal
11

Mira Outttt !!!!
Tuve que enfrentar un problema al implementar un ListViewayer y sus dos tipos de vistas para filas se mezclaron justo después de desplazarlo. A pesar de que la respuesta más votada dentro de este hilo da una buena explicación general, no ha resaltado la información más importante para detener el error de IU anterior que he mencionado.

Aquí está mi explicación:
Ambas getViewTypeCount()y getItemViewType()están siendo utilizadas por BaseAdapterel getViewmétodo de '' para averiguar qué tipo de vista debería ser recuperada, reciclada y devuelta. (como se explica en la respuesta superior dentro del hilo). Pero si no implementa estos dos métodos intuitivamente de acuerdo con el API de Android Doc, entonces podría meterse en el problema que mencioné.

Directriz resumida para la implementación:
para implementar varios tipos de filas Viewsfor ListView, tenemos que implementar esencialmente métodos getItemViewType()y getViewTypeCount()métodos. Y la getItemViewType()documentación nos da una Nota de la siguiente manera:

Nota: Los enteros deben estar en el rango 0de getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPETambién puede ser devuelto.

Por lo tanto, en su getItemViewType()debe devolver los valores para el Tipo de vista, comenzando desde 0, hasta el último tipo como (número de tipos - 1). Por ejemplo, supongamos que solo tiene tres tipos de vistas. Entonces, dependiendo del objeto de datos para la vista, solo puede devolver 0 o 1 o 2 del getItemViewType()método, como un índice de matriz basado en cero. Y como tiene tres tipos de vistas utilizadas, su getViewTypeCount()método debe devolver 3.

En cualquier caso, si devuelve cualquier otro valor entero como 1, 2, 3 o 111, 222, 333 para este método, definitivamente podría experimentar el error de interfaz de usuario anterior que acaba de colocar al no obedecer al Android API Doc.

Si no obtuvo la pista o aún no pudo resolverlo y necesita más información, lea mi respuesta detallada en este hilo de preguntas y respuestas de StackOverflow .

Lea el documento de desarrollador de Android para obtener más información, puede encontrar la pista directamente.

Espero que esta respuesta pueda ser útil para que alguien ahorre muchas horas.

¡¡¡Salud!!!

Randika Vishman
fuente
1
Gracias por mencionar IGNORE_ITEM_VIEW_TYPEque tuve un error en uno de mis ListView. Usé un ArrayAdapter para insertar una vista compuesta de 1 imagen y 2 vistas de texto. Solo tenía un tipo de vista. Intenté no anular el método getItemViewType o anularlo devolviendo la posición o un entero codificado. En todos los casos, estaba experimentando duplicados en mi lista, con un comportamiento extraño al desplazarme (cambios duplicados). Al volver IGNORE_ITEM_VIEW_TYPEal método, se solucionó el problema. Gracias.
Alex
@Alex contento de que te haya sido útil. :-)
Randika Vishman