Exploring ValueNotifier In Flutter

In this post we will be exploring ValueNotifier in Flutter. We will learn how to use ValueNotifier along with the ValueListenableBuilder widget to update error message in a TextField.

Introduction To ValueNotifier In Flutter

In Dart, a ValueNotifier is a special type of class that extends a ChangeNotifer.

A ValueNotifier can hold a single value. The value itself can be of any type. It can be an int, a String, a bool or your own data type.

Using a ValueNotifier improves the performance of Flutter app as it can help to reduce the number times a widget gets rebuilt. In contrast to the setState method which rebuilds the entire widget tree of a StatefulWidget, a ValueNotitier performs a lot better.

Widgets that have subscribed to the ValueNotifier get notified whenever the value is updated.

Setup TextField Validation

For the purpose of this exploration, we will achieve the same feat that we have done when we explored TextField with BLoC pattern.

We will setup a TextField so that it displays error message to the user for invalid entries. If user enters null or empty string, we show an error message. But this time we will be using a ValueNotifier rather than BLoC pattern and Streams.

So, let’s start with a simple Flutter app that has nothing but a TextField.

If you run the code above, you should see a blank TextField interface.

Using A ValueNotifier In Flutter

Now, we declare a ValueNotifier which emits a bool value.

ValueNotifier<bool> _textHasErrorNotifier = ValueNotifier(false);

The _textHasErrorNotifier will be initailly set to false.

For consuming the value notified by our ValueNotifier we use ValueListenableBuilder widget.

What Is A ValueListenableBuilder?

A ValueListenableBuilder is a very useful widget that works well with ValueNotifier. It listens to the value emitted by ValueNotifier and gets rebuilt whenever a new value is emitted.

The constructor of ValueListenableBuilder looks like this:

const ValueListenableBuilder({
    @required this.valueListenable,
    @required this.builder,
    this.child,
  })

where,

valueListenable is the value emitted by the ValueNotifier,

builder is the function that is responsible for building the widget.

We will come back to the optional child parameter later.

Wrap TextField By ValueListenableBuilder

Use the ValueListenableBuilder to create TextField based on the value of _textHasErrorNotifier ValueNotifier.

ValueListenableBuilder(
valueListenable: _textHasErrorNotifier,
builder: (BuildContext context, bool hasError, Widget child) {
   return TextField(
     onChanged: _updateErrorText,
      decoration: InputDecoration(
        fillColor: Colors.grey[100],
        filled: true,
        errorText: hasError ? 'Invalid value entered...' : null,
        enabledBorder: OutlineInputBorder(
          borderSide: BorderSide(
            color: Colors.grey,
          ),
          borderRadius: BorderRadius.circular(6.0),
        ),
...

Here we are updating the ValueNotifier value by calling _updateErrorText function on onChanged callback. The hasError value is then used to show errorText.

The _updateErrorText function simply checks if the entered text is null/empty or not and updates the value of ValueNotifier.

_updateErrorText(String text) {
    var result = (text == null || text == "");
    _textHasErrorNotifier.value = result;
  }

We now have a working ValueNotifer in Flutter app which emits a bool value and a TextField that gets rebuilt whenever the underlying value is changed!

Child Param Of ValueListenableBuilder

Finally, let’s look at the use case of child param of ValueListenableBuilder.

Let’s say in our example TextField we have a prefix icon which always stays the same. Regardless the ValueNotifier emits true or false, prefix icon is going to be constant.

In such case, we can avoid rebuilding the prefix icon by using the child param.

So, the right use of child widget can help prevent unnecessary rebuilds and improve performance of your Flutter app further.

Final Demo

Below we have the final version of our demo app which includes:

  • ValueNotifier use to emit bool value
  • ValueListenableBuilder use to consume value emitted
  • Demonstration Example With TextField

Play around with the demo by entering a value and clearing it back to see the error message being shown and hidden.

TextField Show Error Based On ValueNotifier Value
TextField Show Error Based On ValueNotifier Value