In my application, I defined a provider Song
above MaterialApp
in order to have access to it through my application.
Need: I did this because I have a PageA
which contains a songTitle
variable and a button to go to PageB
.
On PageB
, I have a button that calls my provider Song
and updates PageA
. So when I'm on PageB
and do a Navigator.pop (context)
I come back to PageA
and see the updated songTitle
variable.
To be able to update the PageA
from the PageB
I have to put my provider Song
above MaterialApp
.
==> It works.
My problem: I want to be able to reset my provider when I call PageA
. So if my songTitle
variable had been updated and I quit pageA
, I want my songTitle
variable to return to its default value when I initialize the provider Song
. For the moment the songTitle
variable remains updated all the time ...
Here the router:
abstract class RouterClass{
static Route<dynamic> generate(RouteSettings settings){
final args = settings.arguments;
switch(settings.name){
case RouterName.kMenu:
return CupertinoPageRoute(
builder: (context) => Menu()
);
case RouterName.kPageA:
return CupertinoPageRoute(
builder: (context) => PageA()
);
case RouterName.kPageB:
return CupertinoPageRoute(
builder: (context) => PageB()
);
default:
return CupertinoPageRoute(
builder: (context) => Error404View(title: "Error")
);
}
}
}
The Menu:
class Menu extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Menu'),
),
body : Center(
child: MaterialButton(
onPressed: () {
Navigator.pushNamed(
context,
RouterName.kPageA,
),
},
child: Text('Button'),
),
),
),
);
}
}
The PageA:
class PageA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('pageA'),
),
body : Center(
child: Consumer<Song>(builder: (context, song, child) {
print('Consumer() : ${song.songTitle}');
return Column(
children: <Widget>[
// SONG TITLE
Text(song.songTitle),
// Button
MaterialButton(
onPressed: () => Navigator.pushNamed(
context,
RouterName.kPageB,
),
child: Text('Button'),
),
],
);
}),
),
),
);
}
}
The PageB:
class PageB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('pageB'),
),
body : Center(
child: MaterialButton(
onPressed: () {
Provider.of<Song>(context, listen: false).updateSongTitle('New Title');
},
child: Text('Button'),
),
),
),
);
}
}
The provider Song:
class Song extends ChangeNotifier {
late String songTitle;
Song(){
_initialise();
}
Future _initialise() async
{
songTitle = "Title";
notifyListeners();
}
void updateSongTitle(String newTitle) {
songTitle = newTitle;
notifyListeners();
}
}
Use create
in PageA:
child: ChangeNotifierProvider(
create: (_) => Song(),
child: Consumer<Song>(
builder: (context, song, child) {
print('Consumer() : ${song.songTitle}');
...
Pass your song
object to PageB
:
Navigator.pushNamed(
context,
'/pageB',
arguments: song,
);
Get song
in PageB:
final song = ModalRoute.of(context)!.settings.arguments as Song;
Full code:
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
routes: {
'/': (_) => const HomePage(),
'/pageA': (_) => const PageA(),
'/pageB': (_) => const PageB(),
},
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/pageA',
);
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
),
);
}
}
class PageA extends StatefulWidget {
const PageA({Key? key}) : super(key: key);
@override
State<PageA> createState() => _PageAState();
}
class _PageAState extends State<PageA> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ChangeNotifierProvider(
create: (_) => Song(),
child: Consumer<Song>(
builder: (context, song, child) {
print('Consumer() : ${song.songTitle}');
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// SONG TITLE
Text(song.songTitle),
// Button
MaterialButton(
onPressed: () {
Navigator.pushNamed(
context,
'/pageB',
arguments: song,
);
},
child: const Text('Button'),
),
],
);
},
),
),
),
);
}
}
class PageB extends StatelessWidget {
const PageB({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final song = ModalRoute.of(context)!.settings.arguments as Song;
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: const Text('pageB'),
),
body: Center(
child: MaterialButton(
onPressed: () {
song.updateSongTitle('New Title');
},
child: const Text('Button'),
),
),
),
);
}
}
class Song extends ChangeNotifier {
late String songTitle;
Song() {
_initialise();
}
Future _initialise() async {
songTitle = "Title";
notifyListeners();
}
void updateSongTitle(String newTitle) {
songTitle = newTitle;
notifyListeners();
}
}