Módulo 04: Ecosistema Flutter Profesional

Rendering Optimization

Performance

# Optimización de Rendering en Flutter Lograr 60 (o 120) FPS estables requiere entender qué es costoso y cómo evitarlo. Aquí tienes las mejores prácticas para optimizar el renderizado. ## 1. Minimizar Reconstrucciones (build) El método `build()` debe ser rápido y puro. ### Usa `const` Constructors Si un widget es constante, Flutter sabe que no necesita reconstruirlo nunca, incluso si su padre se reconstruye. ```dart // ✅ Bueno child: const Text('Título Fijo'); // ❌ Malo (se crea una nueva instancia cada vez) child: Text('Título Fijo'); ``` ### Extraer Widgets Divide widgets grandes en widgets pequeños. - Si tienes un `setState` en un widget gigante, todo se reconstruye. - Si extraes la parte que cambia a su propio widget, solo esa parte se reconstruye. ### `Consumer` / `BlocBuilder` Granulares No envuelvas toda tu pantalla en un `BlocBuilder`. Envuélvelo solo en el widget específico que necesita los datos. ## 2. Optimización de Listas (ListView) ### Usa `ListView.builder` Nunca uses `ListView(children: ...)` para listas largas. Eso construye todos los hijos de inmediato (aunque no se vean). `ListView.builder` los construye bajo demanda (lazy). ### `itemExtent` o `prototypeItem` Si tus items tienen altura fija, díselo al ListView. Esto evita que Flutter tenga que calcular la altura de cada item para saber el tamaño total del scroll. ```dart ListView.builder( itemExtent: 50.0, // ✅ Optimización masiva itemBuilder: ... ) ``` ## 3. Evitar "Jank" en Animaciones ### No uses `Opacity` para animaciones Cambiar la opacidad de un widget complejo puede ser costoso porque requiere buffers intermedios. - **Mejor:** Usa `AnimatedOpacity` (optimizado). - **Aún mejor:** Si solo quieres ocultarlo, usa `Visibility`. ### Usa `RepaintBoundary` Si tienes una animación pequeña (ej. un spinner) dentro de una página estática compleja, envuelve la animación en `RepaintBoundary`. Esto le dice a Flutter: "Pinta esto en una capa separada". Así, cuando el spinner gira, no se repinta toda la página, solo la capa del spinner. ```dart RepaintBoundary( child: CircularProgressIndicator(), ) ``` ## 4. Imágenes - **Cache:** Usa `cached_network_image`. - **Tamaño:** No cargues una imagen de 4000x4000px para mostrarla en un icono de 50x50px. Usa `cacheWidth` / `cacheHeight` al cargarla para decodificarla a menor resolución. ```dart Image.network( url, cacheWidth: 100, // Decodifica a este tamaño en memoria ) ``` ## 5. Operaciones Costosas - **Clip:** `ClipRRect`, `ClipPath` son costosos (usan anti-aliasing). Úsalos con moderación. `borderRadius` de un Container es más barato que `ClipRRect`. - **Sombras:** `BoxShadow` es costoso. - **SaveLayer:** Algunas operaciones (como opacidad con grupos o ciertos blend modes) llaman a `saveLayer` en el canvas, que es muy lento (crea una textura off-screen). Chequea el Performance Overlay para ver si abusas de esto. ## Resumen de Optimización 1. **Mide primero:** No optimices a ciegas. Usa DevTools. 2. **Const:** Pon `const` en todo lo que puedas. 3. **Lazy:** Usa builders para listas. 4. **Aísla:** Usa `RepaintBoundary` para separar lo que se mueve de lo estático. 5. **Simplifica:** Menos clips, sombras y opacidades innecesarias.

Este apartado profundiza en los conceptos clave, proporcionando ejemplos prácticos y mejores prácticas para su aplicación en proyectos reales.

Al comprender estos detalles, podrás diseñar soluciones más robustas, mantenibles y escalables en tus aplicaciones Flutter y Dart.