Advertisement
  1. Code
  2. Coding Fundamentals
  3. Tools

Android desde Cero: Entender Adaptadores y Adaptador Vista

Scroll to top
Read Time: 11 min
This post is part of a series called Android From Scratch.
Android From Scratch: Connecting Activities and Applications
Android From Scratch: How to Use Resources In an Application

() translation by (you can also view the original English article)

Los adaptadores de vista son tan universales que tendrías un mal rato tratando de encontrar una aplicación popular de Android sin que las use. El nombre podría sonar familiar, pero si usted cree que nunca antes ha visto un adaptador de vista, entonces probablemente esté equivocado. Cada vez que usted ve una aplicación de Android mostrar un elemento de interfaz de usuario en la forma de una lista, una cuadrícula o en una pila, entonces usted está viendo un adaptador de vista en acción.

Un adaptador de vista, como su nombre lo indica, es un objeto View. Esto significa, que usted puede añadirlo a su activities de la misma forma que usted añade cualquier otro complemento de la interfaz de usuario. Sin embargo, es incapaz de mostrar cualquier dato por su cuenta. Sus contenidos están siempre determinados por otro objeto, un adaptador. En este tutorial, le mostraré como crear adaptadores y usarlos para introducir diferentes tipos de adaptadores de vista tales como ListView y GridView.

¿Cree que sea más fácil aprender con vídeo? Entonces porque no ver nuestros cursos:

1. ¿Qué es un Adaptador?

Un adaptador es un objeto de una clase que implementa la interfaz Adapter. Este actúa como un enlace entre un conjunto de datos y un adaptador vista, un objeto de una clase que extiende a la clase abstracta AdapterView. El conjunto de datos puede ser cualquier cosa que presente datos en una manera estructurada. Arreglos, objetos List y objetos Cursor con usados, por lo general, con conjuntos de datos.

Un adaptador es responsable por recuperar datos desde un conjunto de datos y para generar objetos View mediante esos datos. Los objetos View generados son usados, hasta entonces, para llenar cualquier adaptador vista que esté sujeto al adaptador.

Usted puede crear sus propias clases adaptadores desde cero, sin embargo, la mayoría de los desarrolladores elije usar o heredar las clases adaptadores proporcionadas por el Android SDK, tales como ArrayAdapter y SimpleCursorAdapter. En este tutorial, nos concentraremos en la clase ArrayAdapter.

2. ¿Cómo funciona el Adaptador de Vista?

Los adaptadores de vista pueden mostrar grandes conjuntos de datos muy eficientemente. Por ejemplo, los complementos ListView y GridView pueden mostrar millones de elementos sin ningún retraso notable mientras mantiene la memoria y el uso del CPU muy bajo. ¿Cómo hacen eso? Diferentes adaptadores de vista siguen diferentes estrategias. Sin embargo, esto es lo que la mayoría de ellos normalmente hacen.

  • Ellos reproducen solamente esos objetos View que están, listos en pantalla o que están a punto de moverse en la pantalla. De está manera, la memoria consumida por un adaptador vista puede ser constante e independiente del tamaño del conjunto de datos.
  • Además, permiten a los programadores minimizar las costosas operaciones de formatos exageradas y reciclar objetos View existente que tienen que moverse fuera de la pantalla. Esto conserva bajo el consumo del CPU.

3. Creando un ArrayAdapter

Para crear un adaptador, usted necesita lo siguiente:

  • un conjunto de datos
  • un archivo fuente conteniendo la composición de los objetos View generados

Adicionalmente, debido a que la clase ArrayAdapter sólo puede trabajar con strings, usted necesita asegurarse de que la composición del objeto View generado, contiene al menos, un complemento TextView.

Paso 1: Crear un Conjunto de Datos

La clase ArrayAdapter puede usar los dos; los arreglos y los objetos List como conjuntos de datos. Por ahora, vamos a usar un arreglo como el conjunto de datos.

1
String[] cheeses = {
2
            "Parmesan",
3
            "Ricotta",
4
            "Fontina",
5
            "Mozzarella",
6
            "Cheddar"
7
          };

Paso 2: Crear un Archivo Fuente

Crear un nuevo archivo de formato XML cuyo elemento root es un LinearLayout y nombrelo item.xml.  Arrastre y suelte un complemento Large text dentro de él y ajuste el valor de su atributo id a cheese_name. El archivo de formato XML debería de lucir como este:

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
3
    android:orientation="vertical" android:layout_width="match_parent"
4
    android:layout_height="match_parent"
5
    android:padding="@dimen/activity_horizontal_margin">
6
    <TextView
7
        android:layout_width="wrap_content"
8
        android:layout_height="wrap_content"
9
        android:textAppearance="?android:attr/textAppearanceLarge"
10
        android:text="Large Text"
11
        android:id="@+id/cheese_name" />
12
</LinearLayout>

Paso 3: Crear un Adaptador

En su activity, crear una nueva instancia de la clase ArrayAdapter usando su constructor. Como sus argumentos, pase el nombre del archivo fuente, el identificador de TextView y la referencia al arreglo. Ahora el adaptador está listo.

1
ArrayAdapter<String> cheeseAdapter = 
2
    new ArrayAdapter<String>(this,
3
        R.layout.item,
4
        R.id.cheese_name,
5
        cheeses
6
    );

4. Creando una Lista

Para mostrar una lista de elementos a través de una función desplegable verticalmente, usted puede usar el complemento ListView. Para añadir el complemento a su activity, usted puede arrastre y soltarlo dentro del archivo de formato XML activity o crearlo usando su constructor en su código Java. Por ahora, vamos a hacerlo más tarde.

1
ListView cheeseList = new ListView(this);

Por lo general, ningún otro complemento de interfaz de usuario está colocado dentro de una composición que contiene un ListView. Por lo tanto, pase el ListView al método setContentView() de su activity para que éste ocupe la pantalla completa.

1
setContentView(cheeseList);

Para unir el ListView al adaptador que creamos en el paso anterior, llame al método setAdapter() como se muestra debajo.

1
cheeseList.setAdapter(cheeseAdapter);

Si usted ejecuta su aplicación ahora, entonces podrá ver los contenidos del arreglo en la forma de una lista.

ListView With ArrayAdapterListView With ArrayAdapterListView With ArrayAdapter

5. Creando una Cuadrícula

Para mostrar una cuadrícula de elementos de dos dimensiones a través de una función desplegable verticalmente, usted puede usar el complemento GridView. Tanto ListView y GridView son subclases de la clase abstracta AbsListView y comparten muchas similitudes. Por lo tanto, si usted sabe como usar uno, entonces también sabe como usar el otro.

Use el constructor de la clase GridView para crear una nueva instancia y pásele el método setContentView() de su activity.

1
GridView cheeseGrid = new GridView(this);
2
setContentView(cheeseGrid);

Para ajustar el número de columnas en la cuadrícula, entonces llame su método setNumColumns(). Voy hacer éste una cuadrícula de dos columnas.

1
cheeseGrid.setNumColumns(2);

Generalmente, usted desearía ajustar el ancho de las columnas y el espacio entre ellas usando los métodos setColumnWidth(), setVerticalSpacing() y setHorizontalSpacing(). Observe que estos métodos usan pixeles como su unidad de medida.

1
cheeseGrid.setColumnWidth(60);
2
cheeseGrid.setVerticalSpacing(20);
3
cheeseGrid.setHorizontalSpacing(20);

Ahora puede unir la GridView al adaptador que creamos anteriormente usando el método setAdapter().

1
cheeseGrid.setAdapter(cheeseAdapter);

Ejecute su aplicación otra vez para ver como luce su GridView.

GridView With ArrayAdapterGridView With ArrayAdapterGridView With ArrayAdapter

6. Añadiendo los Eventos Listeners

Es posible escuchar eventos clic o largos clic en los elementos dentro de un adaptador vista. Como un ejemplo, vamos a añadir un evento clic listener a la GridView.

Crear una instancia nueva de la clase anónima que implementa la interfaz AdapterView.OnItemClickListener y páselo al método setOnItemClickListener() para el objeto GridView. Android Studio, automáticamente genera un talonario para el método onItemClick() de la interfaz. Usted observará que los parámetros del método incluyen un entero especificando la posición de la lista de elementos. Usted puede usar este entero para encontrar cual elemento en el conjunto de datos fue sobre el cual el usuario hizo clic.

El siguiente código ilustra como mostrar un simple mensaje como una snackbar de Android, cada vez que un elemento en la GridView es seleccionado con un clic.

1
cheeseGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
2
    @Override
3
    public void onItemClick(AdapterView<?> adapterView,
4
                            View view, int position, long rowId) {
5
6
        // Generate a message based on the position

7
        String message = "You clicked on " + cheeses[position];
8
9
        // Use the message to create a Snackbar

10
        Snackbar.make(adapterView, message, Snackbar.LENGTH_LONG)
11
                .show(); // Show the Snackbar

12
    }
13
});

Si usted ejecuta la aplicación y hace clic sobre cualquier elemento en la cuadrícula, entonces aparecerá un mensaje al fondo de la pantalla. Note que usted puede usar el mismo código para configurar eventos clic listener en los elementos dentro de un ListView.

Snackbar Shown When Items Are ClickedSnackbar Shown When Items Are ClickedSnackbar Shown When Items Are Clicked

7. Extendiendo el ArrayAdapter

Un ArrayAdapter puede controlar sólo un complemento TextView dentro de la composición de los objetos View que éste genero. Para ampliar sus capacidades, usted debe extenderlo. Antes de hacer eso, vamos a crear un conjunto de datos, ligeramente más complejos.

En lugar de strings, digamos que nuestro conjunto de datos contiene objetos de la siguiente clase:

1
static class Cheese {
2
    String name;
3
    String description;
4
5
    public Cheese(String name, String description) {
6
        this.name = name;
7
        this.description = description;
8
    }
9
}

Este es el conjunto de datos que estaremos usando:

1
Cheese[] cheeses = {
2
        new Cheese("Parmesan", "Hard, granular cheese"),
3
        new Cheese("Ricotta", "Italian whey cheese"),
4
        new Cheese("Fontina", "Italian cow's milk cheese"),
5
        new Cheese("Mozzarella", "Southern Italian buffalo milk cheese"),
6
        new Cheese("Cheddar", "Firm, cow's milk cheese"),
7
};

Como puede ver, la clase Cheese contiene dos campos, name y description. Para mostrar los dos campos en una lista o en un cuadrícula, la composición de los elementos debe contener dos complementos TextView.

Crear un archivo nuevo de formato XML y nombrarlo custom_item.xml. Añadir a él un complemento Large text y un Small text. Ajuste el atributo id del primer complemento a cheese_name y para el segundo a cheese_description. Los contenidos del archivo de formato XML ahora debería de lucir así:

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:orientation="vertical" android:layout_width="match_parent"
4
    android:layout_height="match_parent"
5
    android:padding="@dimen/activity_horizontal_margin">
6
    <TextView
7
        android:layout_width="wrap_content"
8
        android:layout_height="wrap_content"
9
        android:textAppearance="?android:attr/textAppearanceLarge"
10
        android:text="Large Text"
11
        android:id="@+id/cheese_name" />
12
    <TextView
13
        android:layout_width="wrap_content"
14
        android:layout_height="wrap_content"
15
        android:textAppearance="?android:attr/textAppearanceSmall"
16
        android:text="Small Text"
17
        android:id="@+id/cheese_description" />
18
</LinearLayout>

El ArrayAdapter, además debe ser capaz de controlar dos complementos TextView. Volver a revisar su activity, crear un nueva clase anónima que hereda la clase ArrayAdapter, y anular su método getView(). Asegúrese que paso el arreglo como un argumento de su constructor.

1
ArrayAdapter<Cheese> cheeseAdapter = 
2
        new ArrayAdapter<Cheese>(this, 0, cheeses) {
3
            @Override
4
            public View getView(int position,
5
                                View convertView,
6
                                ViewGroup parent) {
7
8
            }
9
        };

Dentro del método getView(), debe usar el parámetro de position como un indice del arreglo y buscar el elemento en ese indice.

1
Cheese currentCheese = cheeses[position];

El segundo parámetro del método getView() es lo que nos permite reutilizar los objetos View. Si lo ignora, entonces el desempeño de su adaptador de vista será deficiente. Cuando le método getView() es llamado por primera vez; convertView es null. Debe inicializarlo para llenar el archivo fuente que específica la distribución de los elementos de la lista. Para hacer eso, debe obtener una referencia a LayoutInflater usando el método getLayoutInflater() e invocar su método inflate().

1
// Inflate only once

2
if(convertView == null) {
3
    convertView = getLayoutInflater()
4
                    .inflate(R.layout.custom_item, null, false);
5
}

En este punto, puede usar findViewById() para conseguir una referencia a los complementos TextView dentro de la composición y llamar sus métodos setText() para inicializarlos usando datos desde el arreglo.

1
TextView cheeseName = 
2
    (TextView)convertView.findViewById(R.id.cheese_name);
3
TextView cheeseDescription = 
4
    (TextView)convertView.findViewById(R.id.cheese_description);
5
6
cheeseName.setText(currentCheese.name);
7
cheeseDescription.setText(currentCheese.description);

Finalmente, regrese convertView para que éste pueda ser usado para llenar cualquier adaptador de vista asociado con el adaptador.

1
return convertView;

8. Usando un objeto View Holder

El método getView() es llamado repetidamente por el adaptador vista para rellenarlo. Por lo tanto, usted debe tratar de minimizar el número de operaciones que usted realiza en él.

En los pasos anteriores, usted podría haber notado que, aunque nos hemos asegurado que la distribución de los elementos está presentada sólo una vez, el método findViewById(), el cual consume muchos ciclos del CPU, es llamado cada vez que el método getView() es llamado.

Para evitar esto y para mejorar el desempeño del adaptador de vista, necesitamos almacenar los resultados del método findViewById() dentro del objeto convertView. Para hacer eso, podemos usar un objeto view holder, el cual no es nada más que un objeto de una clase que puede almacenar los complementos presentes en el diseño.

Debido a que el diseño tiene dos complementos TextView, la clase view holder también debe tener dos complementos TextView. He nombrado la clase ViewHolder.

1
static class ViewHolder{
2
    TextView cheeseName;
3
    TextView cheeseDescription;
4
}

En el método getView(), después de que aplicó la clase inflate al diseño, usted puede inicializar el objeto view holder usando el método findViewById().

1
ViewHolder viewHolder = new ViewHolder();
2
viewHolder.cheeseName =
3
        (TextView)convertView.findViewById(R.id.cheese_name);
4
viewHolder.cheeseDescription =
5
        (TextView)convertView.findViewById(R.id.cheese_description);

Para almacenar el objeto view holder en convertView, use su método setTag().

1
// Store results of findViewById

2
convertView.setTag(viewHolder);

Y ahora, cada vez que getView() es llamado, usted puede recuperar el objeto view holder desde convertView usando el método getTag() y actualizando los complementos TextView dentro de él, usando sus métodos setText().

1
TextView cheeseName = 
2
    ((ViewHolder)convertView.getTag()).cheeseName;
3
TextView cheeseDescription = 
4
    ((ViewHolder)convertView.getTag()).cheeseDescription;
5
    
6
cheeseName.setText(currentCheese.name);
7
cheeseDescription.setText(currentCheese.description);

Si usted ejecuta su aplicación, puede ver el GridView mostrando dos líneas de texto en cada celda.

GridView with two lines of text per itemGridView with two lines of text per itemGridView with two lines of text per item

En conclusión

En este tutorial, aprendió a cómo crear un adaptador y usarlo para varios adaptadores de vista. También aprendió a cómo crear su propios adaptadores. Aunque solamente nos enfocamos en la clases ArrayAdapter, ListView y GridView, usted puede usar las mismas técnicas para otros adaptadores y adaptadores de vista que ofrecer Android SDK.

La Android Support Library incluye la clase RecyclerView. Funciona más como un adaptador de vista, pero no es una subclase de la clase AdapterView. Debería de considerar usarlo si desea crear una lista más compleja, especialmente una que use múltiples formatos de archivo para sus elementos. Para aprender más al respecto, puede referirse a este tutorial en Envato Tuts+.

Para aprender más acerca de la clase AdapterView y sus subclases, entonces puede referirse a su documentación.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.