Flutter: Value Notifier

Carlos Costa

Value notifier is a simple class that extends ChangeNotifier and allows you to notify listeners when the value changes.

Example: we will do a simple counter that increments when press a button, our state will be provided by a value notifier.

To start we need 3 files:

  • notifier.dart: will be our value notifier
  • increment_button.dart: will be our component that will increment the counter
  • decrement_button.dart: will be our component that will decrement the counter
//notifier.dart

import 'package:flutter/material.dart';

class _Counter {
  ValueNotifier<int> count = ValueNotifier<int>(0);

  increment() {
    count.value++;
  }

  decrement() {
    count.value--;
  }
}

var counter = _Counter();

Here we create a class called _Counter, that class exposes a ValueNotifier called count and two methods increment and decrement that will increment and decrement the value of count.

Now we will create our two buttons.

//increment_button.dart

import 'package:flutter/material.dart';
import 'controller.dart';

class IncrementButton extends StatelessWidget {
  const IncrementButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: counter.count,
      builder: (context, value, child) {
        return ElevatedButton(
          onPressed: () {
            counter.increment();
          },
          child: SizedBox(
            width: 120,
            child: Center(
              child: Text('Increment: $value'),
            ),
          ),
        );
      },
    );
  }
}
//decrement_button.dart

import 'package:flutter/material.dart';
import 'controller.dart';

class DecrementButton extends StatelessWidget {
  const DecrementButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: counter.count,
      builder: (context, value, child) {
        return ElevatedButton(
          onPressed: () {
            counter.decrement();
          },
          child: SizedBox(
            width: 120,
            child: Center(
              child: Text('Decrement: $value'),
            ),
          ),
        );
      },
    );
  }
}

In these two components we can observe the usage of ValueListenableBuilder. That widget will listen to the changes of ValueNotifier and rebuild the widget when the value changes.

Now we can use our components in our page.

//page.dart

import 'package:flutter/material.dart';
import 'decrement_component.dart';
import 'increment_component.dart';

class Page extends StatelessWidget {
  const Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IncrementButton(),
            SizedBox(height: 20),
            DecrementButton(),
          ],
        ),
      ),
    );
  }
}

The main advantage of using ValueNotifier is that we can use it in any widget and share the same state.

👉 Check the full code here.

References