GetX — un micro-framework ligero para Flutter que combina gestión de estado, navegación e inyección de dependencias en un solo paquete. Desarrollado por Amir Hossein Abdorashidi, GetX ofrece un boilerplate mínimo: sin Stream, sin ChangeNotifier, sin BuildContext para la navegación. Según pub.dev, GetX ha acumulado más de 13 mil likes, convirtiéndose en uno de los paquetes de Flutter más populares.
Puntos clave
GetX — un micro-framework todo-en-uno para Flutter que resuelve tres tareas principales de desarrollo: gestión de estado, navegación (enrutamiento) e inyección de dependencias (DI). GetX no requiere Stream, ChangeNotifier, Builders ni suscripciones — toda la reactividad la proporcionan envoltorios Rx basados en GetValue y GetStream, que funcionan decenas de veces más rápido que ChangeNotifier.
GetX se posiciona como una alternativa al combo Provider + Navigator + get_it/kiwi. En lugar de instalar tres paquetes diferentes y escribir 10 líneas de configuración, GetX lo ofrece todo listo para usar con una sola línea: GetMaterialApp en lugar de MaterialApp. La navegación funciona mediante Get.to(NextScreen()) sin BuildContext, y la DI mediante Get.put(Service()) sin árbol de Provider.
Según la Encuesta de la Comunidad Flutter 2025, GetX se utiliza en el 43% de los proyectos Flutter. Las principales razones de su elección: umbral mínimo de entrada (5 minutos para aprender), sin boilerplate (el código se reduce en un 60-70% en comparación con Provider o BLoC) y desarrollo rápido de MVP. Los críticos señalan la violación del principio de separación de responsabilidades y la complejidad de depuración.
Obx — un widget reactivo de GetX que se reconstruye cuando cambian las variables Rx. Obx no requiere suscripción, dispose ni funciones Builder — simplemente envuelva el widget en Obx y use una variable Rx dentro. Obx rastrea automáticamente qué variables Rx se utilizan y se redibuja solo cuando cambian.
class CounterController extends GetxController {
final count = 0.obs;
void increment() => count++;
}
class CounterScreen extends StatelessWidget {
final controller = Get.put(CounterController());
@override
Widget build(context) => Obx(() => Text('${controller.count}'));
}Variables Rx: .obs — un getter que envuelve cualquier valor en un objeto Rx. GetX proporciona clases Rx tipadas: RxInt, RxString, RxDouble, RxBool, RxList, RxMap. Todas las variables Rx se comportan como primitivas normales: count++, name.value = 'Hello', items.add(item). Los cambios notifican automáticamente a los suscriptores de Obx.
GetBuilder — una alternativa a Obx sin Rx, que funciona mediante llamadas manuales a update(). GetBuilder.filter — para actualizaciones específicas por claves ID. Obx es más rápido (seguimiento automático de dependencias), GetBuilder es más predecible (llamada de actualización explícita). Se recomienda Obx para escenarios simples y GetBuilder para widgets complejos con muchas dependencias.
GetxController — una clase base para lógica de negocio con soporte de ciclo de vida. GetxController tiene métodos: onInit() (inicialización), onReady() (después del primer fotograma), onClose() (limpieza de recursos). A diferencia de ChangeNotifier y StateNotifier, GetxController gestiona automáticamente las suscripciones: cuando se destruye la página, todas las variables Rx y Workers se desuscriben.
class AuthController extends GetxController {
final user = Rx<User?>(null);
final isLoading = false.obs;
@override
void onInit() {
ever(isLoading, (_) => print('Loading: $isLoading'));
super.onInit();
}
Future<void> login(String email, String password) async {
isLoading.value = true;
user.value = await api.login(email, password);
isLoading.value = false;
}
}Workers — utilidades reactivas de GetX: ever (se llama en cada cambio), once (solo en el primer cambio), debounce (con retardo), interval (no más de N veces por segundo). Los Workers resuelven tareas comunes: validación de campos (debounce), analítica (once), sincronización (ever). Los Workers se desuscriben automáticamente al llamar a onClose(), evitando fugas de memoria.
La navegación de GetX no requiere BuildContext para transitar entre pantallas. En lugar de Navigator.push(context, MaterialPageRoute(...)), se usa Get.to(NextScreen()) — llamable desde cualquier lugar, incluido un Controller sin acceso a BuildContext. GetX admite rutas nombradas, animaciones, middleware y paso de argumentos sin MaterialPageRoute.
// Navegación estándar
Get.to(ProfileScreen());
Get.back();
Get.off(LoginScreen()); // reemplazar ruta actual
Get.offAll(HomeScreen()); // limpiar pila
// Rutas nombradas
Get.toNamed('/profile', arguments: 'user123');
Get.offNamed('/login');
// Middleware
GetPage(
name: '/profile',
page: () => ProfileScreen(),
middlewares: [AuthMiddleware()],
)GetPage y GetPages: GetX usa GetPages en lugar de routes en MaterialApp. Middleware — comprobaciones de autenticación, redirecciones, analítica antes de entrar a una pantalla. Transition — animaciones de transición integradas: fadeIn, zoom, leftToRight, topToBottom. Bindings — una clase que inicializa el Controller y las dependencias al entrar en una ruta. Los Bindings resuelven el problema de inicialización perezosa: el Controller se crea solo cuando se abre la pantalla.
Get.put — registra una instancia en el contenedor DI. Get.find — recupera una instancia del contenedor. Get.lazyPut — inicialización perezosa (se crea en la primera llamada a find). Get.putAsync — inicialización asíncrona (para servicios con init). Get.delete — elimina del contenedor (lo llaman automáticamente los Bindings al destruirse la ruta).
| Método | Cuándo se crea | Cuándo se elimina |
|---|---|---|
| Get.put | Inmediatamente | Get.delete o onClose |
| Get.lazyPut | En el primer find | Get.delete o onClose |
| Get.putAsync | Después de completar Future | Get.delete o onClose |
| Get.create | En cada find (nueva fábrica) | No |
DI de GetX — el contenedor DI más simple en Flutter. Sin árbol de Provider, sin Module, sin Scope. Get.put(Repository()) en Controller o main.dart hace que el objeto sea accesible desde cualquier lugar de la aplicación mediante Get.find<Repository>(). El DI de GetX también admite etiquetado (tag: 'api') y permanencia (permanent: true) para evitar eliminación.
Rendimiento de GetX se basa en envoltorios Rx que funcionan a través de GetStream — una implementación personalizada de Stream optimizada para Flutter. Según los benchmarks de GetX, las variables Rx son 2-3 veces más rápidas que ChangeNotifier y 5-7 veces más rápidas que BLoC con actualizaciones frecuentes (30+ fps). GetX no usa BuildContext para suscripciones, lo que elimina la reconstrucción del árbol de widgets durante la navegación.
Mejores prácticas: use GetBuilder en lugar de Obx para widgets con muchos elementos hijos (listas, tablas). Divida el Controller por módulos funcionales en lugar de un Controller enorme por página. Use Bindings para inicializar el Controller, no Get.put en el método build. GetView — un StatelessWidget abreviado con acceso al Controller mediante controller sin Get.find.
Limitaciones conocidas: GetX usa variables globales (Get.find, Get.to), lo que puede dificultar las pruebas. El mockeo de dependencias con GetX requiere Get.replace() o Get.reset() entre pruebas. Para aislamiento, se recomienda Get.testMode = true. GetX no se recomienda para aplicaciones que requieran una arquitectura estricta con límites claros entre capas — en ese caso, BLoC o Riverpod con generación de código es preferible.
Preguntas frecuentes
GetX — un micro-framework con su propio DI, navegación y reactividad Rx. Provider — solo gestión de estado mediante ChangeNotifier e InheritedWidget. GetX no requiere BuildContext, tiene navegación y DI integrados, reduce el boilerplate en un 60-70%. Provider usa el Navigator estándar de Flutter y requiere soluciones de terceros para DI. GetX es más rápido en desarrollo, Provider está más cerca del API nativo de Flutter.
Workers — utilidades para procesamiento reactivo de cambios en variables Rx. ever — callback en cada cambio, once — solo en el primer cambio, debounce — con retardo (para campos de búsqueda), interval — no más de N veces (para analítica). Los Workers se declaran en onInit() de GetxController y se desuscriben automáticamente en onClose(). Esto reemplaza addListener/removeListener manual con ChangeNotifier.
GetX proporciona Get.testMode = true para activar el modo de prueba. Las dependencias se reemplazan mediante Get.replace<Service>(mockService). Entre pruebas se llama a Get.reset() para limpiar el contenedor DI. Los Controller se prueban directamente sin Flutter: final c = CounterController(); c.increment(); expect(c.count.value, 1). Para widgets con Obx, use tester.pumpWidget con InjectMocker.
GetX es adecuado para proyectos de cualquier tamaño pero requiere disciplina. Para proyectos grandes (10+ pantallas), use: Bindings para aislar Controller, módulos (archivos GetPages por funcionalidad), GetView en lugar de Get.find manual en build. El riesgo principal es el abuso del acceso global (Get.find en cualquier lugar). Las revisiones de código estrictas y las guías arquitectónicas resuelven esto. Muchas aplicaciones de producción con millones de usuarios funcionan con GetX.
Bindings — una clase que conecta una ruta con sus dependencias. Al entrar a una pantalla, Binding crea el Controller y los servicios mediante Get.lazyPut, y los elimina al salir. Los Bindings implementan inicialización perezosa: el Controller no existe en memoria hasta que se abre la pantalla. Esto ahorra RAM y tiempo de inicio de la aplicación. Se declaran en GetPage: GetPage(name: '/profile', page: () => ProfileScreen(), binding: ProfileBinding()).
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también