Mar*_*rco 1 state-management flutter flutter-provider riverpod
我遵循了这个 优秀的Riverpod 教程。在最后的步骤中,作者使用了以下代码:
\nfinal _buttonState = Provider<ButtonState>((ref) {\n return ref.watch(timerProvider.state).buttonState;\n});\nfinal buttonProvider = Provider<ButtonState>((ref) {\n return ref.watch(_buttonState);\n});\nRun Code Online (Sandbox Code Playgroud)\n和
\nfinal _timeLeftProvider = Provider<String>((ref) {\n return ref.watch(timerProvider.state).timeLeft;\n});\nfinal timeLeftProvider = Provider<String>((ref) {\n return ref.watch(_timeLeftProvider);\n});\nRun Code Online (Sandbox Code Playgroud)\n我尝试使用_buttonStateand _timeLeftProvider ,据我所知,该应用程序运行正常。所以,我的问题是:
buttonProviderand timeLeftProvider?非常感谢!
\n2020-10-26 更新(main.dart代码和输出图像)
我的main.dart代码是:
import \'package:flutter/material.dart\';\nimport \'package:flutter_hooks/flutter_hooks.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'package:riverpod_timer_app/timer.dart\';\n\nfinal timerProvider = StateNotifierProvider<TimerNotifier>(\n (ref) => TimerNotifier(),\n);\n\nfinal _buttonState = Provider<ButtonState>((ref) {\n return ref.watch(timerProvider.state).buttonState;\n});\n\nfinal buttonProvider = Provider<ButtonState>((ref) {\n return ref.watch(_buttonState);\n});\n\nfinal _timeLeftProvider = Provider<String>((ref) {\n return ref.watch(timerProvider.state).timeLeft;\n});\nfinal timeLeftProvider = Provider<String>((ref) {\n return ref.watch(_timeLeftProvider);\n});\n\nvoid main() {\n runApp(\n const ProviderScope(child: MyApp()),\n );\n}\n\nclass MyApp extends StatelessWidget {\n const MyApp({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n return MaterialApp(\n debugShowCheckedModeBanner: false,\n home: MyHomePage(),\n );\n }\n}\n\nclass MyHomePage extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n print(\'building MyHomePage\');\n\n return Scaffold(\n appBar: AppBar(title: Text(\'My Timer App\')),\n body: Center(\n child: Column(\n mainAxisAlignment: MainAxisAlignment.center,\n children: <Widget>[\n TimerTextWidget(),\n SizedBox(height: 20),\n ButtonsContainer(),\n ],\n ),\n ),\n );\n }\n}\n\nclass TimerTextWidget extends HookWidget {\n const TimerTextWidget({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n final timeLeft = useProvider(timeLeftProvider);\n\n print(\'building TimerTextWidget $timeLeft\');\n\n return Text(\n timeLeft,\n style: Theme.of(context).textTheme.headline2,\n );\n }\n}\n\nclass ButtonsContainer extends HookWidget {\n const ButtonsContainer({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building ButtonsContainer\');\n\n final state = useProvider(buttonProvider);\n\n return Row(\n mainAxisAlignment: MainAxisAlignment.center,\n children: [\n if (state == ButtonState.initial) ...[\n StartButton(),\n ],\n if (state == ButtonState.started) ...[\n PauseButton(),\n SizedBox(width: 20),\n ResetButton(),\n ],\n if (state == ButtonState.paused) ...[\n StartButton(),\n SizedBox(width: 20),\n ResetButton(),\n ],\n if (state == ButtonState.finished) ...[\n ResetButton(),\n ],\n ],\n );\n }\n}\n\nclass StartButton extends StatelessWidget {\n const StartButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building StartButton\');\n return FloatingActionButton(\n onPressed: context.read(timerProvider).start,\n child: Icon(Icons.play_arrow),\n );\n }\n}\n\nclass PauseButton extends StatelessWidget {\n const PauseButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building PauseButton\');\n\n return FloatingActionButton(\n onPressed: context.read(timerProvider).pause,\n child: Icon(Icons.pause),\n );\n }\n}\n\nclass ResetButton extends StatelessWidget {\n const ResetButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building ResetButton\');\n\n return FloatingActionButton(\n onPressed: context.read(timerProvider).reset,\n child: Icon(Icons.replay),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n如果我点击 \xe2\x80\x98Play\xe2\x80\x99 按钮,然后等 10 秒过去,最后我在两种情况下得到相同的结果:
\n\n2020-10-27 更新(不使用and 的main.dart代码)buttonProvidertimeLeftProvider
buttonProvider即使未使用和,这也是输出timeLeftProvider,如下所示main.dart:
import \'package:flutter/material.dart\';\nimport \'package:flutter_hooks/flutter_hooks.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'package:riverpod_timer_app/timer.dart\';\n\nfinal timerProvider = StateNotifierProvider<TimerNotifier>(\n (ref) => TimerNotifier(),\n);\n\nfinal _buttonState = Provider<ButtonState>((ref) {\n return ref.watch(timerProvider.state).buttonState;\n});\n\n// final buttonProvider = Provider<ButtonState>((ref) {\n// return ref.watch(_buttonState);\n// });\n\nfinal _timeLeftProvider = Provider<String>((ref) {\n return ref.watch(timerProvider.state).timeLeft;\n});\n\n// final timeLeftProvider = Provider<String>((ref) {\n// return ref.watch(_timeLeftProvider);\n// });\n\nvoid main() {\n runApp(\n const ProviderScope(child: MyApp()),\n );\n}\n\nclass MyApp extends StatelessWidget {\n const MyApp({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n return MaterialApp(\n debugShowCheckedModeBanner: false,\n home: MyHomePage(),\n );\n }\n}\n\nclass MyHomePage extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n print(\'building MyHomePage\');\n\n return Scaffold(\n appBar: AppBar(title: Text(\'My Timer App\')),\n body: Center(\n child: Column(\n mainAxisAlignment: MainAxisAlignment.center,\n children: <Widget>[\n TimerTextWidget(),\n SizedBox(height: 20),\n ButtonsContainer(),\n ],\n ),\n ),\n );\n }\n}\n\nclass TimerTextWidget extends HookWidget {\n const TimerTextWidget({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n final timeLeft = useProvider(_timeLeftProvider);\n\n print(\'building TimerTextWidget $timeLeft\');\n\n return Text(\n timeLeft,\n style: Theme.of(context).textTheme.headline2,\n );\n }\n}\n\nclass ButtonsContainer extends HookWidget {\n const ButtonsContainer({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building ButtonsContainer\');\n\n final state = useProvider(_buttonState);\n\n return Row(\n mainAxisAlignment: MainAxisAlignment.center,\n children: [\n if (state == ButtonState.initial) ...[\n StartButton(),\n ],\n if (state == ButtonState.started) ...[\n PauseButton(),\n SizedBox(width: 20),\n ResetButton(),\n ],\n if (state == ButtonState.paused) ...[\n StartButton(),\n SizedBox(width: 20),\n ResetButton(),\n ],\n if (state == ButtonState.finished) ...[\n ResetButton(),\n ],\n ],\n );\n }\n}\n\nclass StartButton extends StatelessWidget {\n const StartButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building StartButton\');\n return FloatingActionButton(\n onPressed: context.read(timerProvider).start,\n child: Icon(Icons.play_arrow),\n );\n }\n}\n\nclass PauseButton extends StatelessWidget {\n const PauseButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building PauseButton\');\n\n return FloatingActionButton(\n onPressed: context.read(timerProvider).pause,\n child: Icon(Icons.pause),\n );\n }\n}\n\nclass ResetButton extends StatelessWidget {\n const ResetButton({Key key}) : super(key: key);\n\n @override\n Widget build(BuildContext context) {\n print(\'building ResetButton\');\n\n return FloatingActionButton(\n onPressed: context.read(timerProvider).reset,\n child: Icon(Icons.replay),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我究竟做错了什么?
\n这些提供程序用于防止不必要的重建,但从根本上来说并不是必需的。仅创建您需要的提供程序 - 特别是这些提供程序在应用程序生命周期中永远不会被丢弃,它们只是浪费空间。然而,防止不必要的重建应该是首要任务。
在链接的文章中,作者正在利用包作者推荐的解决方法来防止在侦听 StateNotifier 的特定属性时进行重建。因此,就目前而言,这是完成任务的最有效方法。如果引入新功能来解决这个问题,我将尝试更新这个答案。
我会参考包创建者的示例以获取更多上下文。
下面是一个简单示例,说明了为什么您可以使用多个提供程序来缓存来自外部 API 的响应:
class ExampleApiRepository {
ExampleApiRepository(this._read);
static final provider = Provider((ref) => ExampleApiRepository(ref.read));
final Reader _read;
Future<Example> search(String query) async {
final response = await _call('api/example/$query');
return Example.fromJson(response.data);
}
}
final searchExample = FutureProvider.family<Example, String>((ref, query) async {
return ref.watch(ExampleApiRepository.provider).search(query);
});
Run Code Online (Sandbox Code Playgroud)
在此示例中,如果将相同的查询传递给searchExample提供者,它将返回先前获取的结果。如果没有多个提供商,这可以实现吗?是的——对于大多数情况来说这是正确的。创建提供商关乎便利和效率。因此,不要害怕使用许多提供程序,但不要为了创建它们而创建它们。
也就是说,您链接的文章内容丰富且值得赞赏。
| 归档时间: |
|
| 查看次数: |
4559 次 |
| 最近记录: |