ListView.builder en Flutter

Crea listas eficientes y dinámicas con renderizado lazy

Descargar Ejemplos Completos

¿Qué es ListView.builder?

El ListView.builder es un constructor de ListView que crea elementos bajo demanda. Es extremadamente eficiente para listas largas porque solo renderiza los elementos visibles.

ListView Normal

Item 1
Item 2
Item 3
Item 4
Item 5
+ 95 items más...

Renderiza todos los items al mismo tiempo

ListView.builder

Item 1
Item 2
Item 3
Items 4-100 (virtualizados)

Renderiza solo los items visibles

Sintaxis Básica

Constructor Básico de ListView.builder

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
    );
  },
)

Características Principales:

  • Renderizado lazy: Solo crea los elementos visibles
  • Eficiente con listas largas: Ideal para 100+ elementos
  • Dinámico: Se adapta a cambios en los datos
  • Personalizable: Control total sobre cada item

Parámetros Principales

itemCount

Número total de elementos en la lista

itemCount: myList.length

itemBuilder

Función que construye cada elemento

itemBuilder: (context, index) {
return MyWidget(item[index]);
}

scrollDirection

Dirección del scroll (vertical/horizontal)

scrollDirection: Axis.vertical

¿Cuándo usar ListView.builder?

Listas Largas

Listas con muchos elementos (100+) donde el rendimiento es crucial

// Lista de 1000 usuarios
ListView.builder(
itemCount: users.length,
itemBuilder: (ctx, i) => UserCard(users[i]),
)

Datos Dinámicos

Listas que cambian frecuentemente o se cargan desde API

// Lista de noticias en tiempo real
ListView.builder(
itemCount: news.length,
itemBuilder: (ctx, i) => NewsItem(news[i]),
)

Apps Móviles

Aplicaciones que muestran feeds, chats, o cualquier lista extensa

// Feed de redes sociales
ListView.builder(
itemCount: posts.length,
itemBuilder: (ctx, i) => PostCard(posts[i]),
)

Ejemplos Visuales

1. Lista Básica con ListTile

A
Ana García
ana@email.com
B
Carlos López
carlos@email.com
C
María Rodríguez
maria@email.com
ListView.builder(
  itemCount: users.length,
  itemBuilder: (context, index) {
    return ListTile(
      leading: CircleAvatar(
        child: Text(users[index].name[0]),
      ),
      title: Text(users[index].name),
      subtitle: Text(users[index].email),
      trailing: Icon(Icons.chevron_right),
      onTap: () => navigateToUser(users[index]),
    );
  },
)

2. Lista Horizontal

Categoría 1
Categoría 2
Categoría 3
Categoría 4
ListView.builder(
  scrollDirection: Axis.horizontal,
  itemCount: categories.length,
  itemBuilder: (context, index) {
    return Container(
      margin: EdgeInsets.all(8),
      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Text(categories[index]),
    );
  },
)

3. Lista con Items Personalizados

Producto 1 \$29.99
Descripción del producto
★★★★☆
Producto 2 \$49.99
Descripción del producto
★★★★★
ListView.builder(
  itemCount: products.length,
  itemBuilder: (context, index) {
    return Card(
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(products[index].name),
                Text('\$${products[index].price}'),
              ],
            ),
            SizedBox(height: 8),
            Text(products[index].description),
            SizedBox(height: 8),
            Text('★' * products[index].rating),
          ],
        ),
      ),
    );
  },
)

Propiedades del ListView.builder

Propiedad Tipo Descripción Requerido
itemCount int Número total de elementos en la lista Opcional*
itemBuilder IndexedWidgetBuilder Función que construye cada elemento
scrollDirection Axis Dirección del scroll (vertical/horizontal) No
padding EdgeInsets Espacio alrededor de la lista No
physics ScrollPhysics Comportamiento del scroll No
shrinkWrap bool Si la lista debe ajustar su tamaño No

Nota sobre itemCount:

Si no se proporciona itemCount, la lista será infinita. Esto es útil para listas que se cargan progresivamente o que tienen un número desconocido de elementos.

Generador de ListView.builder

15 items
// El código se generará aquí

ListView.builder vs Alternativas

Widget Ventajas Desventajas Cuándo usar
ListView.builder Eficiente, lazy loading, dinámico Más complejo para listas simples Listas largas o dinámicas
ListView Simple, directo Renderiza todos los items Listas cortas y estáticas
Column Máximo control, flexible No scroll automático, ineficiente Número fijo y pequeño de widgets
GridView.builder Eficiente para grids Complejidad adicional Listas en grid/columnas

Ejercicios Prácticos

Ejercicio 1: Lista de Tareas

Crea una lista de tareas donde cada item muestre el título y estado de completado.

Solución:
ListView.builder(
  itemCount: tasks.length,
  itemBuilder: (context, index) {
    return CheckboxListTile(
      title: Text(tasks[index].title),
      value: tasks[index].completed,
      onChanged: (bool? value) {
        setState(() {
          tasks[index].completed = value!;
        });
      },
    );
  },
)

Ejercicio 2: Lista Infinita

Crea una lista que cargue más elementos cuando el usuario llegue al final.

Solución:
ListView.builder(
  itemCount: items.length + 1,
  itemBuilder: (context, index) {
    if (index == items.length) {
      // Mostrar loading al final
      return Center(child: CircularProgressIndicator());
    }
    return ListTile(title: Text(items[index]));
  },
)

Ejercicio 3: Lista con Diferentes Tipos

Crea una lista que muestre diferentes tipos de widgets según el índice.

Solución:
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    if (index % 3 == 0) {
      return HeaderItem(items[index]);
    } else {
      return ContentItem(items[index]);
    }
  },
)

Consejos y Mejores Prácticas

✅ Lo que SÍ debes hacer

  • Usa keys únicas para items que pueden cambiar
  • Implementa paginación para listas muy largas
  • Usa const constructores en itemBuilder cuando sea posible
  • Considera usar ScrollController para control avanzado

❌ Lo que NO debes hacer

  • No uses setState dentro de itemBuilder
  • Evita cálculos pesados en itemBuilder
  • No olvides el itemCount en listas infinitas
  • No uses ListView.builder para listas muy cortas

Tip Profesional

Para listas extremadamente largas, considera usar ListView.separated() que permite definir un separador personalizado entre items, mejorando el rendimiento y la apariencia.