Saltearse al contenido

RtProvider

Esta página aún no está disponible en tu idioma.

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.

    RtProvider<T>(
    T instanceBuilder(), {
    Key? key,
    String? id,
    DependencyMode mode = DependencyMode.builder,
    Widget? child,
    Widget builder(
    BuildContext context,
    T instance,
    Widget? child,
    )?,
    })
  • RtProvider.init : This constructor initializes the dependency instance before it is mounted.

    RtProvider<T>.init(
    T instanceBuilder(), {
    Key? key,
    String? id,
    DependencyMode mode = DependencyMode.builder,
    Widget? child,
    Widget builder(
    BuildContext context,
    T instance,
    Widget? child,
    )?,
    })
  • RtProvider.lazy : This constructor defers the instantiation of the dependency until it is accessed for the first time.

    RtProvider<T>.lazy(
    T instanceBuilder(), {
    Key? key,
    String? id,
    DependencyMode mode = DependencyMode.builder,
    Widget? child,
    Widget builder(
    BuildContext context,
    Widget? child,
    )?,
    })

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
const Counter({Key? key}) : super(key: key);
7
8
@override
9
Widget build(BuildContext context) {
10
// Provide the `CounterController` dependency to the widget tree
11
return RtProvider<CounterController>(
12
() => CounterController(),
13
builder: (context, counterController, child) {
23 collapsed lines
14
return Row(
15
mainAxisSize: MainAxisSize.min,
16
children: [
17
ElevatedButton(
18
onPressed: counterController.decrement,
19
child: const Icon(Icons.remove),
20
),
21
const SizedBox(width: 8),
22
// Observe the `count` property of the `counterController`
23
// and rebuild the widget tree when the `count` value changes
24
RtConsumer<CounterController>(
25
listenStates: (counterController) => [counterController.count],
26
builder: (context, counterController, child) {
27
return Text("${counterController.count}");
28
},
29
),
30
const SizedBox(width: 8),
31
ElevatedButton(
32
onPressed: counterController.increment,
33
child: const Icon(Icons.add),
34
),
35
],
36
);
37
},
38
);
39
}
40
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
4
class CounterView extends StatelessWidget {
5
const CounterView({Key? key}) : super(key: key);
6
7
@override
8
Widget build(BuildContext context) {
9
return Scaffold(
10
appBar: AppBar(
11
title: const Text("Counter"),
12
),
13
body: const Center(
14
child: Counter(),
15
),
16
);
17
}
18
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
final String? id;
7
8
const Counter({Key? key, this.id}) : super(key: key);
9
10
@override
11
Widget build(BuildContext context) {
12
// Provide the `CounterController` dependency to the widget tree
13
return RtProvider<CounterController>(
14
() => CounterController(),
15
id: id,
16
builder: (context, counterController, child) {
24 collapsed lines
17
return Row(
18
mainAxisSize: MainAxisSize.min,
19
children: [
20
ElevatedButton(
21
onPressed: counterController.decrement,
22
child: const Icon(Icons.remove),
23
),
24
const SizedBox(width: 8),
25
// Observe the `count` property of the `counterController`
26
// and rebuild the widget tree when the `count` value changes
27
RtConsumer<CounterController>(
28
id: id,
29
listenStates: (counterController) => [counterController.count],
30
builder: (context, counterController, child) {
31
return Text("${counterController.count}");
32
},
33
),
34
const SizedBox(width: 8),
35
ElevatedButton(
36
onPressed: counterController.increment,
37
child: const Icon(Icons.add),
38
),
39
],
40
);
41
},
42
);
43
}
44
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
4
class CounterView extends StatelessWidget {
5
const CounterView({Key? key}) : super(key: key);
6
7
@override
8
Widget build(BuildContext context) {
9
return Scaffold(
10
appBar: AppBar(
11
title: const Text("Counter"),
12
),
13
body: Center(
14
child: Column(
15
mainAxisAlignment: MainAxisAlignment.center,
16
children: const [
17
Counter(id: 'counter1'),
18
SizedBox(height: 8),
19
Counter(id: 'counter2'),
20
SizedBox(height: 8),
21
Counter(id: 'counter1'),
22
],
23
),
24
),
25
);
26
}
27
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
final InstanceChildBuilder<CounterController>? builder;
7
8
const Counter({Key? key, this.builder}) : super(key: key);
9
10
Widget build(BuildContext context) {
11
// Provide the `CounterController` dependency to the widget tree
12
return RtProvider<CounterController>(
13
() => CounterController(), // Registers the `CounterController` dependency
14
child: RtConsumer<CounterController>(
15
// Observe the `count` property of the `counterController` instance
16
listenStates: (counterController) => [counterController.count],
17
builder: (context, counterController, child) {
18
// Rebuilds the widget tree when the `count` value changes
19
return Text("${counterController.count}");
20
},
21
),
22
builder: builder,
23
);
24
}
25
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
4
class CounterWithButtons extends StatelessWidget {
5
const CounterWithButtons({Key? key}) : super(key: key);
6
7
Widget build(BuildContext context) {
8
return Counter(
9
builder: (context, counterController, child) {
10
return Column(
11
mainAxisAlignment: MainAxisAlignment.center,
12
children: [
13
Row(
14
mainAxisAlignment: MainAxisAlignment.center,
15
children: [
16
ElevatedButton(
17
onPressed: counterController.decrement,
18
child: const Icon(Icons.remove),
19
),
20
const SizedBox(width: 8),
21
if (child != null) child,
22
const SizedBox(width: 8),
23
ElevatedButton(
24
onPressed: counterController.increment,
25
child: const Icon(Icons.add),
26
),
27
],
28
),
29
],
30
);
31
},
32
);
33
}
34
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
import 'counter_with_buttons.dart';
4
5
class CounterView extends StatelessWidget {
6
const CounterView({Key? key}) : super(key: key);
7
8
@override
9
Widget build(BuildContext context) {
10
return Scaffold(
11
appBar: AppBar(
12
title: const Text('Counter'),
13
),
14
body: const Center(
15
child: CounterWithButtons(),
16
),
17
floatingActionButton: const CircleAvatar(
18
child: Counter(),
19
),
20
);
21
}
22
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}

Immediate initialization

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
const Counter({Key? key}) : super(key: key);
7
8
@override
9
Widget build(BuildContext context) {
10
// Immediately initializes the `CounterController` dependency for providing it to the widget tree
11
final widgetToRender = RtProvider<CounterController>.init(
12
() {
13
print('CounterController created');
14
return CounterController();
15
},
16
builder: (context, counterController, child) {
23 collapsed lines
17
return Row(
18
mainAxisSize: MainAxisSize.min,
19
children: [
20
ElevatedButton(
21
onPressed: counterController.decrement,
22
child: const Icon(Icons.remove),
23
),
24
const SizedBox(width: 8),
25
// Observe the `count` property of the `counterController`
26
// and rebuild the widget tree when the `count` value changes
27
RtConsumer<CounterController>(
28
listenStates: (counterController) => [counterController.count],
29
builder: (context, counterController, child) {
30
return Text("${counterController.count}");
31
},
32
),
33
const SizedBox(width: 8),
34
ElevatedButton(
35
onPressed: counterController.increment,
36
child: const Icon(Icons.add),
37
),
38
],
39
);
40
},
41
);
42
43
// The `CounterController` instance can be use here
44
// to call methods or access properties
45
Rt.get<CounterController>()?.count.value = 10;
46
47
// A render delay of 10 seconds
48
return FutureBuilder(
49
future: Future.delayed(
50
const Duration(seconds: 10),
51
() => widgetToRender,
52
),
53
builder: (context, snapshot) {
54
if (!snapshot.hasData) {
55
return const Center(
56
child: CircularProgressIndicator(),
57
);
58
}
59
60
return snapshot.data as Widget;
61
});
62
}
63
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
4
class CounterView extends StatelessWidget {
5
const CounterView({Key? key}) : super(key: key);
6
7
@override
8
Widget build(BuildContext context) {
9
return Scaffold(
10
appBar: AppBar(
11
title: const Text('Counter'),
12
),
13
body: const Center(
14
child: Counter(),
15
),
16
);
17
}
18
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
const Counter({Key? key}) : super(key: key);
7
8
@override
9
Widget build(BuildContext context) {
10
// Provide the `CounterController` dependency to the widget tree
11
return RtProvider<CounterController>.lazy(
12
() {
13
print('CounterController created');
14
return CounterController();
15
},
16
builder: (context, child) {
17
final showCounter = Signal(false);
18
19
return RtSignalWatcher(
20
builder: (context, child) {
21
if (!showCounter.value) {
22
return ElevatedButton(
23
onPressed: () => showCounter.value = true,
24
child: const Text('Show Counter'),
25
);
26
}
27
28
// In this line, the `CounterController` instance will be created
29
final counterController = context.use<CounterController>();
30
31
return Row(
22 collapsed lines
32
mainAxisSize: MainAxisSize.min,
33
children: [
34
ElevatedButton(
35
onPressed: counterController.decrement,
36
child: const Icon(Icons.remove),
37
),
38
const SizedBox(width: 8),
39
// Observe the `count` property of the `counterController`
40
// and rebuild the widget tree when the `count` value changes
41
RtConsumer<CounterController>(
42
listenStates: (counterController) =>
43
[counterController.count],
44
builder: (context, counterController, child) {
45
return Text("${counterController.count}");
46
},
47
),
48
const SizedBox(width: 8),
49
ElevatedButton(
50
onPressed: counterController.increment,
51
child: const Icon(Icons.add),
52
),
53
],
54
);
55
},
56
);
57
},
58
);
59
}
60
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter.dart';
3
4
class CounterView extends StatelessWidget {
5
const CounterView({Key? key}) : super(key: key);
6
7
@override
8
Widget build(BuildContext context) {
9
return Scaffold(
10
appBar: AppBar(
11
title: const Text('Counter'),
12
),
13
body: const Center(
14
child: Counter(),
15
),
16
);
17
}
18
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}

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:

1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter_controller.dart';
4
5
class Counter extends StatelessWidget {
6
final DependencyMode mode;
7
8
const Counter({Key? key, required this.mode}) : super(key: key);
9
10
@override
11
Widget build(BuildContext context) {
12
// Provide the `CounterController` dependency to the widget tree
13
return RtProvider<CounterController>(
14
() => CounterController(),
15
id: mode.toString(),
16
mode: mode,
17
builder: (context, counterController, child) {
24 collapsed lines
18
return Row(
19
mainAxisSize: MainAxisSize.min,
20
children: [
21
ElevatedButton(
22
onPressed: counterController.decrement,
23
child: const Icon(Icons.remove),
24
),
25
const SizedBox(width: 8),
26
// Observe the `count` property of the `counterController`
27
// and rebuild the widget tree when the `count` value changes
28
RtConsumer<CounterController>(
29
id: mode.toString(),
30
listenStates: (counterController) => [counterController.count],
31
builder: (context, counterController, child) {
32
return Text("${counterController.count}");
33
},
34
),
35
const SizedBox(width: 8),
36
ElevatedButton(
37
onPressed: counterController.increment,
38
child: const Icon(Icons.add),
39
),
40
],
41
);
42
},
43
);
44
}
45
}
1
import 'package:flutter/material.dart';
2
import 'package:flutter_reactter/flutter_reactter.dart';
3
import 'counter.dart';
4
import 'counter_controller.dart';
5
6
class CounterView extends StatelessWidget {
7
const CounterView({Key? key}) : super(key: key);
8
9
@override
10
Widget build(BuildContext context) {
11
final showCounter = Signal(false);
12
13
_listenLifecycle();
14
15
return Scaffold(
16
appBar: AppBar(
17
title: const Text('Counter'),
18
),
19
body: Center(
20
child: RtSignalWatcher(
21
child: ElevatedButton(
22
onPressed: () => showCounter.value = !showCounter.value,
23
child: showCounter.value
24
? Text("Hide Counters")
25
: Text("Show Counters"),
26
),
27
builder: (context, child) {
28
return Column(
29
children: [
30
child!,
31
if (showCounter.value) ...[
32
const SizedBox(height: 8),
33
// Will register and create the `CounterController` dependency each time.
34
const Counter(mode: DependencyMode.builder),
35
const SizedBox(height: 8),
36
// Will register the `CounterController` dependency only once.
37
const Counter(mode: DependencyMode.factory),
38
const SizedBox(height: 8),
39
// Will register and create the `CounterController` dependency only once,
40
// this keeps the counter value between rebuilds
41
const Counter(mode: DependencyMode.singleton),
42
],
43
],
44
);
45
},
46
),
47
),
48
);
49
}
50
51
void _listenLifecycle() {
52
for (final mode in DependencyMode.values) {
53
Rt.on(
54
RtDependency<CounterController>(
55
mode.toString(),
56
),
57
Lifecycle.registered,
58
(_, __) {
59
print("CounterController registered with ${mode.toString()}.");
60
},
61
);
62
63
Rt.on(
64
RtDependency<CounterController>(
65
mode.toString(),
66
),
67
Lifecycle.created,
68
(_, __) {
69
print("CounterController created with ${mode.toString()}.");
70
},
71
);
72
73
Rt.on(
74
RtDependency<CounterController>(
75
mode.toString(),
76
),
77
Lifecycle.deleted,
78
(_, __) {
79
print("CounterController deleted with ${mode.toString()}.");
80
},
81
);
82
83
Rt.on(
84
RtDependency<CounterController>(
85
mode.toString(),
86
),
87
Lifecycle.unregistered,
88
(_, __) {
89
print("CounterController unregistered with ${mode.toString()}.");
90
},
91
);
92
}
93
}
94
}
1
import 'package:reactter/reactter.dart';
2
3
class CounterController {
4
// Create a reactive state using the `Signal` class
5
final count = Signal(0);
6
7
void increment() {
8
count.value++;
9
}
10
11
void decrement() {
12
count.value--;
13
}
14
}
1
import 'package:flutter/material.dart';
2
import 'counter_view.dart';
3
4
void main() {
5
runApp(MyApp());
6
}
7
8
class MyApp extends StatelessWidget {
9
@override
10
Widget build(BuildContext context) {
11
return MaterialApp(
12
home: CounterView(),
13
);
14
}
15
}