The RtProvider
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 RtProvider
class has three constructors, each catering to different dependency injection needs.
RtProvider
: Default constructor that provides a dependency using a builder function.
DependencyMode mode = DependencyMode . builder ,
RtProvider . init
: This constructor initializes the dependency instance before it is mounted.
DependencyMode mode = DependencyMode . builder ,
RtProvider . lazy
: This constructor defers the instantiation of the dependency until it is accessed for the first time.
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 T
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
that remains static while the widget tree is rebuilt.
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 RtProvider
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 RtProviders
widget.
Usage
Basic Usage
To use RtProvider
, 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) {
// Provide the `CounterController` dependency to the widget tree
return RtProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observe the `count` property of the `counterController`
// and rebuild the widget tree when the `count` value changes
RtConsumer < 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
RtProvider
offers the id
property that allows you to provide an identifier for the dependency.
This 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) {
// Provide the `CounterController` dependency to the widget tree
return RtProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observe the `count` property of the `counterController`
// and rebuild the widget tree when the `count` value changes
RtConsumer < 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
RtProvider
offers the child
property to pass a widget that is independent of the RtProvider
and is passed to the builder
function.
This 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) {
// Provide the `CounterController` dependency to the widget tree
return RtProvider < CounterController >(
() => CounterController () , // Registers the `CounterController` dependency
child : RtConsumer < CounterController >(
// Observe 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 RtProvider . 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 = RtProvider < 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 ) ,
// Observe the `count` property of the `counterController`
// and rebuild the widget tree when the `count` value changes
RtConsumer < 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
Rt . 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 RtProvider . 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) {
// Provide the `CounterController` dependency to the widget tree
return RtProvider < 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 ) ,
// Observe the `count` property of the `counterController`
// and rebuild the widget tree when the `count` value changes
RtConsumer < 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
RtProvider
provides a mode
property 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) {
// Provide the `CounterController` dependency to the widget tree
return RtProvider < CounterController >(
() => CounterController () ,
builder : (context , counterController , child) {
mainAxisSize : MainAxisSize . min ,
onPressed : counterController . decrement ,
child : const Icon ( Icons . remove) ,
const SizedBox (width : 8 ) ,
// Observe the `count` property of the `counterController`
// and rebuild the widget tree when the `count` value changes
RtConsumer < 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' ;
import 'package:flutter_reactter/flutter_reactter.dart' ;
import 'counter_controller.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.
const Counter (mode : DependencyMode . builder) ,
const SizedBox (height : 8 ) ,
// Will register the `CounterController` dependency only once.
const Counter (mode : DependencyMode . factory ) ,
const SizedBox (height : 8 ) ,
// Will register and create the `CounterController` dependency only once,
// this keeps the counter value between rebuilds
const Counter (mode : DependencyMode . singleton) ,
void _listen Lifecycle () {
for ( final mode in DependencyMode . values) {
RtDependency < CounterController >(
print ( "CounterController registered with ${ mode . toString ()} ." ) ;
RtDependency < CounterController >(
print ( "CounterController created with ${ mode . toString ()} ." ) ;
RtDependency < CounterController >(
print ( "CounterController deleted with ${ mode . toString ()} ." ) ;
RtDependency < 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) {