While building our web app, we face a challenge. Firstly, we need to merge multiple providers. To solve this issue we have used a multi provider.
As a result, it improves the readability of our code. Secondly, it reduces boilerplate code. Why? Because otherwise we have to nest multiple layers of providers which doesn’t sound practical.
Consider the following code.
Provider<FirstUser>(
create: (_) => FirstUser(),
child: Provider<SecondUser>(
create: (_) => SecondUser(),
child: Provider<ThirdUser>(
create: (_) => ThirdUser(),
child: MaterialApp(),
),
),
),
We cannot go on doing this forever. It’d be better to write this way:
MultiProvider(
providers: [
Provider<FirstUser>(create: (_) => FirstUser()),
Provider<SecondUser>(create: (_) => SecondUser()),
Provider<ThirdUser>(create: (_) => ThirdUser()),
],
child: MaterialApp(),
)
We see that the MultiProvider class has a property called “providers” which expects a list of Providers.
As an outcome, it becomes much easier for us to provide any type to a child widget.
Suppose we want to provide three different types of data to a child widget.
![Data Provider Flutter](https://i0.wp.com/sanjibsinha.com/wp-content/uploads/2022/05/Data-Provider-Flutter.jpg?ssl=1)
Firstly, we will provide a user defined type or object User.
Secondly, we provide a String data type, and finally we provide an integer data type.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../model/custom_theme.dart';
import 'second_app.dart';
class ClassTitle {
late String title;
ClassTitle(this.title);
}
class FirstApp extends StatelessWidget {
const FirstApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<ClassTitle>(
create: (context) => ClassTitle('John\'s Blog'),
),
Provider<String>(
create: (context) => 'John',
),
Provider<int>(
create: (context) => 23,
),
],
child: MaterialApp(
title: 'Angel\'s Blog',
theme: CustomTheme.theme,
home: const SecondApp(),
),
);
}
}
We’re going to provide these different data types to the child widget SecondApp().
For example, now we can grab those data types quite easily in the child widget.
Let’s see the code.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'first_app.dart';
class SecondApp extends StatelessWidget {
const SecondApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final title = Provider.of<ClassTitle>(context);
final name = Provider.of<String>(context);
final age = Provider.of<int>(context);
return Scaffold(
appBar: AppBar(
title: Text(
title.title,
style: const TextStyle(
color: Colors.black,
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text.rich(
TextSpan(
text: 'Your name is ',
style: const TextStyle(
color: Colors.black,
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
children: <InlineSpan>[
WidgetSpan(
alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: Text(
name,
style: Theme.of(context).textTheme.headline2,
),
),
),
const TextSpan(
text: '.',
),
],
),
),
const SizedBox(
height: 40.0,
),
TextButton(
onPressed: () {},
child: Text(
'Your age is $age',
style: const TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.black,
backgroundColor: Colors.yellow,
),
),
),
],
),
),
);
}
}
Without the multi provider it would have become clumsy. Because we had to nest the providers which is not a good practice.
Certainly the multi provider class solves the problem in an elegant manner.
Leave a Reply