'How to retain the state of the app when navigating to another screen in flutter using riverpod
Good day, guys
I'm new to using Riverpod, I have a counter app that when the FAB button is tapped it increases the counter by 1. This works well using Riverpod ChangeNotifierProvider. The issue I'm currently having is retaining the state of the counter in the second screen when I click on another button that takes the user to the second screen.
Below is my code
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod_app/counter.dart';
import 'package:flutter_riverpod_app/second_screen.dart';
final counterProvider = ChangeNotifierProvider<Counter>((ref) => Counter());
void main() {
runApp(ProviderScope(
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Consumer(builder: (context, watch, _) {
final count = watch(counterProvider);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${count.count}',
style: Theme.of(context).textTheme.headline4,
),
FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => SecondScreen()));
},
child: Text('Go to second screen'))
],
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read(counterProvider).updateCount(),
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
second_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_riverpod_app/counter.dart';
final counterProvider = ChangeNotifierProvider<Counter>((ref) => Counter());
class SecondScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, watch) {
final counter = watch(counterProvider);
return Scaffold(
appBar: AppBar(
title: Text('Second Screen'),
),
body: Center(
child: Text('${counter.count}', style: TextStyle(fontSize: 30,),),
),
);
}
}
counter.dart
import 'package:flutter/foundation.dart';
class Counter extends ChangeNotifier {
int count = 0;
updateCount() {
count++;
notifyListeners();
}
}
I don't really know how to get the state of the counter on the second screen, if it was the Provider Package, all I just have to do on the second screen was to use Provider.of<counter>(context, listen: false).counter
and it will display the counter.
Solution 1:[1]
The problem is that you created the Provider twice. You only want to create it once and access it globally.
Remove final counterProvider = ChangeNotifierProvider<Counter>((ref) => Counter());
from your SecondScreen and instead import the counterProvider from your FirstScreen and it will behave as you expect.
Solution 2:[2]
In misc/global.dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
final kCounterProvider = StateProvider((ref) => 0);
In screen/riverpod_screen.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter_kitchensink/src/misc/global.dart' as global;
class RiverpodScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: Text('Riverpod'),
),
body: Container(
child: Center(
child: Text(ref.watch(global.kCounterProvider).toString()),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(global.kCounterProvider.notifier).state++;
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
In screen/riverpod2_screen.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter_kitchensink/src/misc/global.dart' as global;
class Riverpod2Screen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: Text('Riverpod2'),
),
body: Container(
child: Center(
child: Text(ref.watch(global.kCounterProvider).toString()),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(global.kCounterProvider.notifier).state++;
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Alex Hartford |
Solution 2 | exiang |