使用 riverpod 在 flutter 中导航到另一个屏幕时如何保留应用程序的状态
How to retain the state of the app when navigating to another screen in flutter using riverpod
大家好
我刚开始使用 Riverpod,我有一个计数器应用程序,当点击 FAB 按钮时,它会将计数器加 1。使用 Riverpod ChangeNotifierProvider 效果很好。
我目前遇到的问题是,当我单击将用户带到第二个屏幕的另一个按钮时,会保留第二个屏幕中的计数器状态。
下面是我的代码
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();
}
}
我真的不知道如何在第二个屏幕上获取计数器的状态,如果它是 Provider Package,我只需要在第二个屏幕上使用 Provider.of<counter>(context, listen: false).counter
和它将显示计数器。
问题是您创建了两次提供程序。您只想创建一次并全局访问它。
从您的 SecondScreen 中删除 final counterProvider = ChangeNotifierProvider<Counter>((ref) => Counter());
,而是从您的 FirstScreen 中导入 counterProvider,它将按您的预期运行。
在misc/global.dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
final kCounterProvider = StateProvider((ref) => 0);
在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),
),
);
}
}
在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),
),
);
}
}
大家好
我刚开始使用 Riverpod,我有一个计数器应用程序,当点击 FAB 按钮时,它会将计数器加 1。使用 Riverpod ChangeNotifierProvider 效果很好。 我目前遇到的问题是,当我单击将用户带到第二个屏幕的另一个按钮时,会保留第二个屏幕中的计数器状态。
下面是我的代码
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();
}
}
我真的不知道如何在第二个屏幕上获取计数器的状态,如果它是 Provider Package,我只需要在第二个屏幕上使用 Provider.of<counter>(context, listen: false).counter
和它将显示计数器。
问题是您创建了两次提供程序。您只想创建一次并全局访问它。
从您的 SecondScreen 中删除 final counterProvider = ChangeNotifierProvider<Counter>((ref) => Counter());
,而是从您的 FirstScreen 中导入 counterProvider,它将按您的预期运行。
在misc/global.dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
final kCounterProvider = StateProvider((ref) => 0);
在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),
),
);
}
}
在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),
),
);
}
}