The ReactterProvider
widget injects a dependency into its descendant widgets, ensuring the dependency is accessible throughout its subtree. It facilitates sharing the dependency across multiple widgets seamlessly.
Syntax
The ReactterProvider
class has three constructors, each catering to different dependency injection needs.
ReactterProvider
: Default constructor that provides a dependency using a builder function.
DependencyMode mode = DependencyMode . builder ,
ReactterProvider . init
: This constructor initializes the dependency instance before it is mounted.
ReactterProvider < T > . init (
DependencyMode mode = DependencyMode . builder ,
ReactterProvider . lazy
: This constructor defers the instantiation of the dependency until it is accessed for the first time.
ReactterProvider < T > . lazy (
DependencyMode mode = DependencyMode . builder ,
Properties
instanceBuilder
: A function that creates an instance of the T
dependency. This function is registered by Dependency Injection .
key
: An optional Key
to use for identifying the widget.
id
: An optional identifier for the dependency.
If omitted, the dependency will be located by its type( T
).
mode
: The mode of the dependency injection. By default, it uses the builder mode(DependecyMode . builder
).
Learn more about the dependency modes .
child
: An optional Widget
which is independent of the ReactterProvider
.
If defined, it is passed to the builder
function if it is defined.
builder
: An optional function which builds a widget based on the dependency. If it not defined, the child
widget is returned.
It receives the following arguments:
context
: The BuildContext
of the widget. A handle to the location of ReactterProvider
in the widget tree.
instance
: The instance of the T
dependency. It is available only to default constructor.
child
: The child
widget passed to the ReactterProviders
widget.
Usage
Basic Usage
To use the ReactterProvider
widget, wrap it around the widget tree where you want to inject the dependency.
Here’s an example of how to use it:
counter . dart
counter_controller.dart
counter_view.dart
main.dart
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
const Counter ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
// Provides the `CounterController` dependency to the widget tree
return ReactterProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observes the `count` property of the `counterController`
// and rebuilds the widget tree when the `count` value changes
ReactterConsumer < CounterController >(
listenStates : (counterController) => [counterController . count] ,
builder : (context , counterController , child) {
return Text ( " ${ counterController . count } " ) ;
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
title : const Text ( "Counter" ) ,
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {
Using id
The ReactterProvider
widget provides an id
argument that allows you to provide an identifier for the dependency.
It is useful when you want to create multiple instances of the same dependency.
Here’s an example of how to use it:
counter . dart
counter_view . dart
counter_controller.dart
main.dart
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
const Counter ({ Key ? key , this . id}) : super (key : key) ;
Widget build ( BuildContext context) {
// Provides the `CounterController` dependency to the widget tree
return ReactterProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observes the `count` property of the `counterController`
// and rebuilds the widget tree when the `count` value changes
ReactterConsumer < CounterController >(
listenStates : (counterController) => [counterController . count] ,
builder : (context , counterController , child) {
return Text ( " ${ counterController . count } " ) ;
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
import 'package:flutter/material.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
title : const Text ( "Counter" ) ,
mainAxisAlignment : MainAxisAlignment . center ,
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {
Using child
The ReactterProvider
widget provides a child
argument that does not rebuild when the dependency changes.
It is useful when you want to reuse a widget.
Here’s an example of how to use it:
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
final InstanceChildBuilder < CounterController > ? builder ;
const Counter ({ Key ? key , this . builder}) : super (key : key) ;
Widget build ( BuildContext context) {
// Provides the `CounterController` dependency to the widget tree
return ReactterProvider < CounterController >(
() => CounterController () , // Registers the `CounterController` dependency
child : ReactterConsumer < CounterController >(
// Observes the `count` property of the `counterController` instance
listenStates : (counterController) => [counterController . count] ,
builder : (context , counterController , child) {
// Rebuilds the widget tree when the `count` value changes
return Text ( " ${ counterController . count } " ) ;
import 'package:flutter/material.dart' ;
class CounterWithButtons extends StatelessWidget {
const CounterWithButtons ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
builder : (context , counterController , child) {
mainAxisAlignment : MainAxisAlignment . center ,
mainAxisAlignment : MainAxisAlignment . center ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
if (child != null ) child ,
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
import 'package:flutter/material.dart' ;
import 'counter_with_buttons.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
title : const Text ( 'Counter' ) ,
child : CounterWithButtons () ,
floatingActionButton : const CircleAvatar (
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {
The ReactterProvider . init
constructor initializes the dependency before it is mounted. It is useful when you want to initialize the dependency immediately.
Here’s an example of how to use it:
counter . dart
counter_controller.dart
counter_view.dart
main.dart
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
const Counter ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
// Immediately initializes the `CounterController` dependency for providing it to the widget tree
final widgetToRender = ReactterProvider < CounterController > . init (
print ( 'CounterController created' ) ;
return CounterController () ;
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observes the `count` property of the `counterController`
// and rebuilds the widget tree when the `count` value changes
ReactterConsumer < CounterController >(
listenStates : (counterController) => [counterController . count] ,
builder : (context , counterController , child) {
return Text ( " ${ counterController . count } " ) ;
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
// The `CounterController` instance can be use here
// to call methods or access properties
Reactter . get < CounterController >() ? . count . value = 10 ;
// A render delay of 10 seconds
const Duration (seconds : 10 ) ,
builder : (context , snapshot) {
child : CircularProgressIndicator () ,
return snapshot . data as Widget ;
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
title : const Text ( 'Counter' ) ,
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {
Initialization lazily
The ReactterProvider . lazy
constructor initializes the dependency lazily. It creates the dependency only when it is accessed for the first time.
Here’s an example of how to use it:
counter . dart
counter_controller.dart
counter_view.dart
main.dart
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
const Counter ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
// Provides the `CounterController` dependency to the widget tree
return ReactterProvider < CounterController > . lazy (
print ( 'CounterController created' ) ;
return CounterController () ;
builder : (context , child) {
final showCounter = Signal ( false ) ;
builder : (context , child) {
if ( ! showCounter . value) {
onPressed : () => showCounter . value = true ,
child : const Text ( 'Show Counter' ) ,
// In this line, the `CounterController` instance will be created
final counterController = context . use < CounterController >() ;
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observes the `count` property of the `counterController`
// and rebuilds the widget tree when the `count` value changes
ReactterConsumer < CounterController >(
listenStates : (counterController) =>
[counterController . count] ,
builder : (context , counterController , child) {
return Text ( " ${ counterController . count } " ) ;
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
title : const Text ( 'Counter' ) ,
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {
Initialization modes
The ReactterProvider
widget provides a mode
argument that allows you to initialize the dependency with different modes .
Here’s an example of how to use it:
counter . dart
counter_view . dart
counter_controller.dart
main.dart
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.dart' ;
class Counter extends StatelessWidget {
final DependencyMode mode ;
const Counter ({ Key ? key , required this . mode}) : super (key : key) ;
Widget build ( BuildContext context) {
// Provides the `CounterController` dependency to the widget tree
return ReactterProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observes the `count` property of the `counterController`
// and rebuilds the widget tree when the `count` value changes
ReactterConsumer < CounterController >(
listenStates : (counterController) => [counterController . count] ,
builder : (context , counterController , child) {
return Text ( " ${ counterController . count } " ) ;
const SizedBox (width : 8 ) ,
onPressed : counterController . increment ,
child : const Icon ( Icons . add) ,
import 'package:Counter/counter_controller.dart' ;
import 'package:flutter/material.dart' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
class CounterView extends StatelessWidget {
const CounterView ({ Key ? key}) : super (key : key) ;
Widget build ( BuildContext context) {
final showCounter = Signal ( false ) ;
title : const Text ( 'Counter' ) ,
onPressed : () => showCounter . value = ! showCounter . value ,
builder : (context , child) {
if (showCounter . value) ... [
const SizedBox (height : 8 ) ,
// Will register and create the `CounterController` dependency each time.
mode : DependencyMode . builder ,
const SizedBox (height : 8 ) ,
// Will register the `CounterController` dependency only once.
mode : DependencyMode . factory ,
const SizedBox (height : 8 ) ,
// Will register and create the `CounterController` dependency only once,
// this keeps the counter value between rebuilds
mode : DependencyMode . singleton ,
void _listen Lifecycle () {
for ( final mode in DependencyMode . values) {
ReactterDependency < CounterController >(
print ( "CounterController registered with ${ mode . toString ()} ." ) ;
ReactterDependency < CounterController >(
print ( "CounterController created with ${ mode . toString ()} ." ) ;
ReactterDependency < CounterController >(
print ( "CounterController deleted with ${ mode . toString ()} ." ) ;
ReactterDependency < CounterController >(
print ( "CounterController unregistered with ${ mode . toString ()} ." ) ;
import 'package:reactter/reactter.dart' ;
class CounterController {
// Create a reactive state using the ` Signal ` class
import 'package:flutter/material.dart' ;
import 'counter_view.dart' ;
class MyApp extends StatelessWidget {
Widget build ( BuildContext context) {