Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Builder widget for ChangeNotifier in Flutter

Background

  • A ValueNotifier has a ValueListenableBuilder widget.
  • A Stream has a StreamBuilder widget.
  • A Future has a FutureBuilder widget.

Question

  • What is the builder for ChangeNotifier?

What I tried

I tried using a ValueListenableBuilder with ChangeNotifier but ChangeNotifier doesn't implement ValueListenable.

I know I could use ChangeNotifierProvider from the Provider package, but I'd like to know if there is a solution that doesn't require a third-party package.

like image 562
Suragch Avatar asked Apr 09 '21 04:04

Suragch


People also ask

What is the use of ChangeNotifier in Flutter?

ChangeNotifier is a class that provides change notification to its listeners. That means you can subscribe to a class that is extended or mixed in with ChangeNotifier and call its notifyListeners() method when there's a change in that class.

What is builder widget in Flutter?

A builder is a Flutter design pattern in which the construction code of a widget is defined outside of its class. Builder functions are callback interfaces that pass data (often layout-specific) to the parent widget which returns a child based on that data.

How do I put widgets on top of another in Flutter?

In Flutter, the overlay lets you print visual elements on top of other widgets by inserting them into the overlay's stack. You insert a widget into the overlay using an OverlayEntry and you use Positioned and AnimatedPositioned to choose where the entry is positioned within the overlay.

Where do I put ChangeNotifierProvider?

We already know where to put ChangeNotifierProvider : above the widgets that need to access it. In the case of CartModel , that means somewhere above both MyCart and MyCatalog . You don't want to place ChangeNotifierProvider higher than necessary (because you don't want to pollute the scope).

What is the specialty of change notifier class in flutter?

What is the specialty of change notifier class in flutter? Although the main specialty is ChangeNotifierProvider listens to ChangeNotifier, it has many other advantages. In this article we will also listen to these special powers of ChangeNotifier. We consider ourselves just like other subscribers that listen to ChangeNotifier.

What is a builder in flutter?

A stateless utility widget whose build method uses its builder callback to create the widget's child. Builder (Flutter Widget of the Week) This widget is a simple inline alternative to defining a StatelessWidget subclass. For example a widget defined and used like this:

What is a valuelistenablebuilder in flutter?

A widget whose content stays synced with a ValueListenable. Given a ValueListenable<T> and a builder which builds widgets from concrete values of T, this class will automatically register itself as a listener of the ValueListenable and call the builder with updated values when the value changes. ValueListenableBuilder (Flutter Widget of the Week)

What is the difference between animatedbuilder and notificationlistener?

AnimatedBuilder, which also triggers rebuilds from a Listenable without passing back a specific value from a ValueListenable. NotificationListener, which lets you rebuild based on Notification coming from its descendant widgets rather than a ValueListenable that you have a direct reference to.


Video Answer


3 Answers

ChangeNotifier is a direct implementation of the Listenable Widget and for the Listenable, you can use AnimatedBuilder, which triggers rebuilds from a Listenable without passing back a specific value Also, your class could extend from ChangeNotifier and add new capability to it and you can create a custom Builder widget base on these new functionalities

like image 57
Amir Hossein Mirzaei Avatar answered Oct 13 '22 21:10

Amir Hossein Mirzaei


This is a supplemental answer demonstrating using an AnimatedBuilder to rebuild the UI on a change from a ChangeNotifier.

It's just the standard counter app.

counter_model.dart

import 'package:flutter/foundation.dart';

class CounterModel extends ChangeNotifier {
  int _counter = 0;

  int get count => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

main.dart

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _counterModel = CounterModel();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            AnimatedBuilder(
              animation: _counterModel,
              builder: (context, child) {
                return Text(
                  '${_counterModel.count}',
                  style: Theme.of(context).textTheme.headline4,
                );
              }
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _counterModel.increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}
like image 18
Suragch Avatar answered Oct 13 '22 19:10

Suragch


You can wirte a simple widget by yourself. use setState as a listener for a ChangeNotifier.

class ChangeNotifierBuilder<T extends ChangeNotifier> extends StatefulWidget {
  const ChangeNotifierBuilder({
    Key? key,
    required this.value,
    required this.builder,
  }) : super(key: key);

  final T value;

  final Widget Function(BuildContext context, T value) builder;

  @override
  _ChangeNotifierBuilderState<T> createState() =>
      _ChangeNotifierBuilderState<T>();
}

class _ChangeNotifierBuilderState<T extends ChangeNotifier>
    extends State<ChangeNotifierBuilder<T>> {
  @override
  void initState() {
    widget.value.addListener(_listener);
    super.initState();
  }

  @override
  void didUpdateWidget(covariant ChangeNotifierBuilder<T> oldWidget) {
    if (widget.value != oldWidget.value) {
      _miggrate(widget.value, oldWidget.value, _listener);
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    widget.value.removeListener(_listener);
    super.dispose();
  }

  void _miggrate(Listenable a, Listenable b, void Function() listener) {
    a.removeListener(listener);
    b.addListener(listener);
  }

  void _listener() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, widget.value);
  }
}
like image 3
kvii2202 Avatar answered Oct 13 '22 19:10

kvii2202