Skip to content

Más Funciones Watch

Ya aprendiste watchValue() para observar propiedades ValueListenable. Ahora exploremos las otras funciones watch.

watchIt - Observar Objeto Completo en get_it

Cuando tu objeto registrado ES un Listenable, usa watchIt():

dart
// Manager that IS a ChangeNotifier
class TodoManagerChangeNotifier extends ChangeNotifier {
  List<String> _todos = [];
  List<String> get todos => _todos;

  void addTodo(String todo) {
    _todos.add(todo);
    notifyListeners(); // Notify on changes
  }
}

// Watch the whole manager
class TodoList extends WatchingWidget {
  @override
  Widget build(BuildContext context) {
    final manager = watchIt<TodoManagerChangeNotifier>();

    return ListView.builder(
      itemCount: manager.todos.length,
      itemBuilder: (context, index) => Text(manager.todos[index]),
    );
  }
}

Cuándo usar watchIt():

  • Tu objeto extiende ChangeNotifier o ValueNotifier
  • Necesitas llamar métodos en el objeto
  • El objeto completo notifica cambios

watch - Observar Cualquier Listenable

watch() es el más flexible - observa CUALQUIER Listenable:

dart
class CounterWidget extends WatchingWidget {
  const CounterWidget({super.key, required this.counter});

  final ValueNotifier<int> counter;

  @override
  Widget build(BuildContext context) {
    // Watch the counter passed as parameter (not from get_it)
    final count = watch(counter).value;

    return Column(
      children: [
        Text('Count: $count'),
        ElevatedButton(
          onPressed: () => counter.value++,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

Cuándo usar watch():

  • Observar objetos Listenable locales
  • Ya tienes una referencia al Listenable
  • Caso más genérico

watch() es la Base

watch() es la función más flexible - podrías usarla para reemplazar watchIt() y watchValue():

dart
// Estos son equivalentes:
final manager = watchIt<CounterManager>();
final manager = watch(di<CounterManager>());

// Estos son equivalentes:
final count = watchValue((CounterManager m) => m.count);
final count = watch(di<CounterManager>().count).value;

¿Por qué usar las funciones de conveniencia?

  • watchIt() es más limpio para obtener el objeto completo de get_it
  • watchValue() proporciona mejor inferencia de tipos y sintaxis más limpia
  • Cada una está optimizada para su caso de uso específico

Usar watch() Solo para Disparar Reconstrucciones

A veces no necesitas el valor de retorno - solo quieres disparar una reconstrucción cuando un Listenable cambia:

dart
class FormWidget extends WatchingWidget {
  const FormWidget({super.key, required this.controller});

  final TextEditingController controller;

  @override
  Widget build(BuildContext context) {
    // Watch the controller just to trigger rebuild - don't need the return value
    watch(controller);

    // Now we can use the controller's current state in our widget tree
    return Column(
      children: [
        TextField(controller: controller),
        Text('Character count: ${controller.text.length}'),
        ElevatedButton(
          onPressed: controller.text.isEmpty ? null : () => print('Submit'),
          child: Text('Submit'),
        ),
      ],
    );
  }
}

Puntos clave:

  • watch(controller) dispara reconstrucción cuando el controller notifica
  • No usamos el valor de retorno - solo llamamos watch() por el efecto secundario
  • El widget se reconstruye, así que controller.text.length siempre está actualizado
  • El estado de habilitación/deshabilitación del botón se actualiza automáticamente

watchPropertyValue - Actualizaciones Selectivas

Solo se reconstruye cuando una propiedad específica de un objeto padre Listenable cambia:

Firma del método:

dart
R watchPropertyValue<T extends Listenable, R>(
  R Function(T) selector,
  {String? instanceName, GetIt? getIt}
)
dart
class ThemeSwitch extends WatchingWidget {
  @override
  Widget build(BuildContext context) {
    // Only rebuilds when darkMode changes, not language or fontSize
    final darkMode = watchPropertyValue((SettingsModel m) => m.darkMode);

    return Switch(
      value: darkMode,
      onChanged: (value) => di<SettingsModel>().setDarkMode(value),
    );
  }
}

La diferencia:

dart
// Rebuilds on EVERY SettingsModel change
final settings = watchIt<SettingsModel>();
final darkMode1 = settings.darkMode;

// Rebuilds ONLY when darkMode changes
final darkMode2 = watchPropertyValue((SettingsModel m) => m.darkMode);

Comparación Rápida

dart
// 1. watchValue - Watch ValueListenable property from get_it
final todos = watchValue((TodoManager m) => m.todos);

// 2. watchIt - When manager is a Listenable registered in get_it
final manager = watchIt<CounterModel>();

// 3. watch - Local or direct Listenable
final counter = createOnce(() => ValueNotifier(0));
final count = watch(counter).value;

// 4. watchPropertyValue - Selective updates from Listenable registered in get_it
final darkMode = watchPropertyValue((SettingsModel m) => m.darkMode);

Elegir la Función Correcta

Si tienes solo una o dos propiedades que deberían disparar una actualización:

Usa ValueNotifier para cada propiedad y watchValue():

dart
final data = watchValue((DataManager m) => m.data);

Si el objeto completo puede ser actualizado o muchas propiedades pueden cambiar:

Usa ChangeNotifier y watchIt():

dart
final manager = watchIt<CounterModel>();

O si el rendimiento es importante, usa watchPropertyValue() para actualizaciones selectivas:

dart
// Only rebuild when THIS specific property changes
final darkMode = watchPropertyValue((SettingsModel m) => m.darkMode);

Para Listenables locales no registrados en get_it:

Usa watch():

dart
final text = watch(controller).value.text;

Ejemplo Práctico

Mezclando diferentes funciones watch:

dart
class Dashboard extends WatchingWidget {
  @override
  Widget build(BuildContext context) {
    // watchValue - for ValueListenable property
    final userName = watchValue((SimpleUserManager m) => m.name);

    // watchPropertyValue - selective rebuild
    final darkMode = watchPropertyValue((SettingsModel m) => m.darkMode);

    // watch - local state
    final searchQuery = createOnce(() => ValueNotifier<String>(''));
    final query = watch(searchQuery).value;

    return Scaffold(
      appBar: AppBar(
        title: Text('Hello, $userName'),
        backgroundColor: darkMode ? Colors.black : Colors.blue,
      ),
      body: Column(
        children: [
          TextField(
            onChanged: (value) => searchQuery.value = value,
          ),
          Text('Searching: $query'),
        ],
      ),
    );
  }
}

Puntos Clave

watchValue() - Observa propiedades ValueListenable desde get_it (una o dos propiedades) ✅ watchIt() - Observa objetos Listenable completos desde get_it (muchas propiedades cambian) ✅ watchPropertyValue() - Actualizaciones selectivas desde Listenable en get_it (optimización de rendimiento) ✅ watch() - Más flexible, cualquier Listenable (local o parámetro) ✅ Elige basándote en el número de propiedades y patrones de actualización ✅ Mezcla y combina según tus necesidades

Siguiente: Aprende sobre observar múltiples valores.

Ver También

Publicado bajo la Licencia MIT.