¿Cómo funciona el método getView () al crear su propio adaptador personalizado?

101

Mis preguntas son:

  1. ¿Cuál es exactamente la función del LayoutInflater?
  2. ¿Por qué todos los artículos que he leído comprueban primero si convertview es nulo o no? ¿Qué significa cuando es nulo y qué significa cuando no lo es?
  3. ¿Cuál es el parámetro principal que acepta este método?
GrowinMan
fuente

Respuestas:

115

1: El LayoutInflatertoma sus archivos XML de diseño y crea diferentes objetos de visualización a partir de su contenido.

2: Los adaptadores están diseñados para reutilizar Vistas, cuando una Vista se desplaza para que ya no sea visible, se puede usar para una de las nuevas Vistas que aparecen. Esta vista reutilizada es la convertView. Si esto es nulo significa que no hay una Vista reciclada y tenemos que crear una nueva, de lo contrario deberíamos usarla para evitar crear una nueva.

3: Se parentproporciona para que pueda inflar su vista en eso para los parámetros de diseño adecuados.

Todos estos juntos pueden usarse para crear efectivamente la vista que aparecerá en su lista (u otra vista que requiera un adaptador):

public View getView(int position, @Nullable View convertView, ViewGroup parent){
    if (convertView == null) {
        //We must create a View:
        convertView = inflater.inflate(R.layout.my_list_item, parent, false);
    }
    //Here we can do changes to the convertView, such as set a text on a TextView 
    //or an image on an ImageView.
    return convertView;
}

Observe el uso de LayoutInflater, que parentse puede usar como argumento para ello, y cómo convertViewse reutiliza.

Jave
fuente
5
Convertview == null es útil cuando todos sus elementos siguen el mismo diseño. Cuando necesita buscar una radio o un botón marcado, por ejemplo, y cambiar el diseño en función de cada elemento, debe volver a inflar o obtiene la vista en caché.
sagits
No es necesario volver a inflar demasiado. Solo necesita escribir switch o if-else ladder en getview e inflar las vistas de acuerdo con su caso, anular public int getItemViewType (int position) y public int getViewTypeCount (). @sagits
Prashanth Debbadwar
Si las declaraciones generalmente funcionan, pero al usar botones de opción, editar textos y este tipo de cosas, tuve problemas al usar vistas en caché, hay algunas preguntas sobre estas cosas en el desbordamiento de la pila.
Sagits
71

getView()método en el adaptador es de la opinión de elemento de generación de un ListView, Gallery, ...

  1. LayoutInflaterse utiliza para obtener la vista de objetos que se define en un diseño xml (el objeto raíz, normalmente LinearLayout, FrameLayouto RelativeLayout)

  2. convertViewes para reciclar. Supongamos que tiene una vista de lista que solo puede mostrar 10 elementos a la vez, y actualmente muestra el elemento 1 -> elemento 10. Cuando se desplaza hacia abajo un elemento, el elemento 1 estará fuera de la pantalla y el elemento 11 se mostrará . Para generar Vista para el elemento 11, se llamará al método getView (), y convertViewaquí está la vista del elemento 1 (que ya no es necesario). Entonces, en su lugar, cree un nuevo objeto View para el elemento 11 (que es costoso), ¿por qué no reutilizarlo convertView? => solo verificamos si convertViewes nulo o no, si es nulo, crea una nueva vista, de lo contrario, la reutiliza convertView.

  3. parentViewes ListView o Gallery ... que contiene la vista del elemento que getView()genera.

Nota : no llama a este método directamente, solo necesita implementarlo para indicarle a la vista principal cómo generar la vista del elemento.

Anh Tuan
fuente
2
EXCELENTE explicación para parentView, no puedo encontrar una mejor explicación que esta, +1
Ahmed Adel Ismail
¡Increíble explicación!
gabi
gran explicación +1
tpk
8

Podrías ver este video sobre la vista de lista. Es de Google IO del año pasado y sigue siendo el mejor recorrido por las vistas de lista en mi mente.

http://www.youtube.com/watch?v=wDBM6wVEO70

  1. Infla diseños (los archivos xml en su carpeta res / layout /) en objetos java como LinearLayout y otras vistas.

  2. Mire el video, lo pondrá al día con el uso de la vista de conversión, básicamente es una vista reciclada que espera ser reutilizada por usted, para evitar crear un nuevo objeto y ralentizar el desplazamiento de su lista.

  3. Le permite hacer referencia a su vista de lista desde el adaptador.

erbsman
fuente
5

¿Cuál es exactamente la función del LayoutInflater?

Cuando diseña utilizando XML, todos los elementos de la interfaz de usuario son solo etiquetas y parámetros. Antes de poder utilizar estos elementos de la interfaz de usuario (por ejemplo, TextView o LinearLayout), debe crear los objetos reales correspondientes a estos elementos xml. Para eso está el inflador. El inflador utiliza estas etiquetas y sus parámetros correspondientes para crear los objetos reales y establecer todos los parámetros. Después de esto, puede obtener una referencia al elemento de la interfaz de usuario usando findViewById ().

¿Por qué todos los artículos que he leído comprueban primero si convertview es nulo o no? ¿Qué significa cuando es nulo y qué significa cuando no lo es?

Este es uno interesante. Verá, se llama a getView () cada vez que se dibuja un elemento de la lista. Ahora, antes de poder dibujar el elemento, debe crearse. Ahora convertView es básicamente la última vista utilizada para dibujar un elemento. En getView (), primero infla el xml y luego usa findByViewID () para obtener los diversos elementos de la interfaz de usuario del listitem. Cuando verificamos (convertView == null) lo que hacemos es verificar que si una vista es nula (para el primer elemento), luego crearla, de lo contrario, si ya existe, reutilizarla, no es necesario volver a realizar el proceso de inflado. . Lo hace mucho más eficiente.

También debe haber encontrado un concepto de ViewHolder en getView (). Esto hace que la lista sea más eficiente. Lo que hacemos es crear un marcador de visualización y almacenar la referencia a todos los elementos de la interfaz de usuario que obtuvimos después de inflar. De esta manera, podemos evitar llamar a los numerosos findByViewId () y ahorrar mucho tiempo. Este ViewHolder se crea en la condición (convertView == null) y se almacena en convertView usando setTag (). En el bucle else lo obtenemos nuevamente usando getView () y lo reutilizamos.

¿Cuál es el parámetro principal que acepta este método?

El padre es un ViewGroup al que finalmente se adjunta su vista creada por getView (). Ahora, en su caso, este sería ListView.

Espero que esto ayude :)

Shubhayu
fuente
4
  1. El inflador de diseño infla / agrega XML externo a su vista actual.

  2. getView () se llama varias veces, incluso cuando se desplaza. Entonces, si ya tiene la vista inflada, no queremos volver a hacerlo, ya que inflar es un proceso costoso ... por eso verificamos si es nulo y luego lo inflamos.

  3. La vista principal es una sola celda de su Lista.

ngesh
fuente
3
La vista principal se explica incorrectamente aquí. Será el ListView no el ListItem
Varun Jain
2

LayoutInflaterse utiliza para generar vistas dinámicas del XML para el ListViewelemento o en onCreateViewel fragmento.

ConvertViewse utiliza básicamente para reciclar las vistas que no están en la vista actualmente. Digamos que tiene un scrollable ListView. Al desplazarse hacia abajo o hacia arriba, convertViewmuestra la vista que se desplazó. Esta reutilización ahorra memoria.

El parámetro principal del getView()método da una referencia al diseño principal que tiene listView. Supongamos que desea obtener la identificación de cualquier elemento en el XML principal que puede usar:

ViewParent nv = parent.getParent();

while (nv != null) {

    if (View.class.isInstance(nv)) {
        final View button = ((View) nv).findViewById(R.id.remove);
        if (button != null) {
            // FOUND IT!
            // do something, then break;
            button.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.d("Remove", "Remove clicked");

                    ((Button) button).setText("Hi");
                }
            });
        }
        break;
    }

 }
user936414
fuente
1

getView()método crear nuevo Viewo ViewGrouppara cada fila de Listviewo Spinner. Puede definir esto Viewo ViewGroupen un Layout XMLarchivo en res/layoutcarpeta y puede darle la referencia a la Adapterclase Object.

si tiene 4 elementos en una matriz pasada al adaptador. getView()El método creará 4 vistas para 4 filas de Adaper.

La clase LayoutInflater tiene un método inflate () que crea un objeto de vista desde el diseño de recursos XML.

Ravi1187342
fuente
0

También puede encontrar información útil sobre getView en la interfaz del adaptador en el archivo Adapter.java. Dice;

/**
 * Get a View that displays the data at the specified position in the data set. You can either
 * create a View manually or inflate it from an XML layout file. When the View is inflated, the
 * parent View (GridView, ListView...) will apply default layout parameters unless you use
 * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
 * to specify a root view and to prevent attachment to the root.
 * 
 * @param position The position of the item within the adapter's data set of the item whose view
 *        we want.
 * @param convertView The old view to reuse, if possible. Note: You should check that this view
 *        is non-null and of an appropriate type before using. If it is not possible to convert
 *        this view to display the correct data, this method can create a new view.
 *        Heterogeneous lists can specify their number of view types, so that this View is
 *        always of the right type (see {@link #getViewTypeCount()} and
 *        {@link #getItemViewType(int)}).
 * @param parent The parent that this view will eventually be attached to
 * @return A View corresponding to the data at the specified position.
 */
View getView(int position, View convertView, ViewGroup parent);
Hamza Polat
fuente