# Garbage Collector en Dart
Dart es un lenguaje con gestión automática de memoria. Utiliza un **Garbage Collector (GC)** generacional avanzado para asignar y liberar memoria sin intervención del programador.
## ¿Cómo funciona la Memoria en Dart?
La memoria Heap (donde viven los objetos) se divide en dos espacios principales:
1. **Young Space (Espacio Joven)**: Para objetos nuevos y de vida corta.
2. **Old Space (Espacio Viejo)**: Para objetos que sobreviven mucho tiempo.
### 1. Young Space (Scavenger)
- **Diseñado para:** Objetos temporales (widgets stateless, variables locales, eventos).
- **Algoritmo:** Copying Collector (Cheney's algorithm).
- **Velocidad:** Extremadamente rápido.
- **Frecuencia:** Muy alta.
Cuando creas un objeto, se asigna aquí. Cuando el espacio se llena, el GC:
1. Identifica los objetos "vivos" (referenciados).
2. Los copia a una nueva mitad del espacio.
3. Ignora los objetos muertos (se sobrescriben).
**Importante:** En Flutter, los Widgets son inmutables y de vida corta. El Scavenger está optimizado para limpiar miles de widgets por frame sin causar "jank".
### 2. Old Space (Mark-Sweep-Compact)
- **Diseñado para:** Objetos persistentes (singletons, datos en caché, estado de la app).
- **Algoritmo:** Mark-Sweep y Mark-Compact.
- **Velocidad:** Más lento.
- **Frecuencia:** Baja.
Si un objeto sobrevive a varios ciclos del Scavenger, es "promovido" al Old Space.
## Optimizaciones para Flutter
El GC de Dart tiene hooks específicos para Flutter:
- **Idle Time Collection:** Si la app está inactiva (no hay animaciones ni toques), el GC aprovecha para limpiar memoria sin afectar el rendimiento.
- **Memory Pressure:** Si el sistema operativo avisa que hay poca RAM, el GC se vuelve más agresivo.
## Memory Leaks (Fugas de Memoria)
Aunque hay GC, puedes tener fugas de memoria si mantienes referencias a objetos que ya no necesitas.
### Causas Comunes
1. **Listeners no cancelados:**
```dart
// ❌ Leak: StreamSubscription nunca se cancela
void initState() {
someStream.listen((data) => updateUi(data));
}
// ✅ Correcto
StreamSubscription? _sub;
void initState() {
_sub = someStream.listen((data) => updateUi(data));
}
void dispose() {
_sub?.cancel();
super.dispose();
}
```
2. **Controladores no dispuestos:**
- `TextEditingController`
- `AnimationController`
- `ScrollController`
- Siempre llama a `.dispose()`.
3. **Variables estáticas globales:**
- Mantienen objetos vivos por siempre.
4. **Closures que capturan `context`:**
- Ten cuidado al guardar closures que hacen referencia a un `BuildContext` de un widget que ya no existe.
## Herramientas de Diagnóstico
Usa **Dart DevTools** para analizar la memoria:
1. **Memory View:** Ver gráfico de uso de memoria en tiempo real.
2. **Allocation Profile:** Ver cuántos objetos de cada tipo existen.
3. **Heap Snapshot:** Tomar una "foto" de la memoria para buscar leaks.
## Conclusión
- Dart usa un GC generacional (Young/Old space).
- La creación de objetos de vida corta (Widgets) es muy barata.
- Debes liberar recursos manuales (Streams, Controllers) usando `dispose()`.
- El GC trabaja con Flutter para minimizar pausas durante animaciones.
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.