Flutter Riverpod:点击按钮后才开始监听Provider的实现方案
解决方案
有两种实用方法能实现点击按钮后才开始监听Provider,且后续持续跟踪状态变化:
方式一:用StatefulWidget控制监听时机
把原ConsumerWidget改成StatefulWidget,通过内部状态控制是否启动监听:
final userNameProvider = StateProvider((ref) => 'text'); class Example extends StatefulWidget { const Example({super.key}); @override State<Example> createState() => _ExampleState(); } class _ExampleState extends State<Example> { bool _startListening = false; @override Widget build(BuildContext context) { return Consumer( builder: (context, ref, child) { // 仅开启监听后才调用watch获取Provider值 final userName = _startListening ? ref.watch(userNameProvider) : null; return Column( children: [ if (_startListening) Text(userName ?? ''), Text("some text"), ElevatedButton( onPressed: () { setState(() { _startListening = true; }); }, child: const Text('开始监听') ) ], ); }, ); } }
方式二:新增Provider控制监听开关
如果想保留ConsumerWidget的无状态特性,可以加一个控制监听状态的Provider:
final userNameProvider = StateProvider((ref) => 'text'); // 新增开关Provider,控制是否启动监听 final listenSwitchProvider = StateProvider((ref) => false); class Example extends ConsumerWidget { const Example({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final startListening = ref.watch(listenSwitchProvider); // 开关开启后才监听目标Provider final userName = startListening ? ref.watch(userNameProvider) : null; return Column( children: [ if (startListening) Text(userName ?? ''), Text("some text"), ElevatedButton( onPressed: () { ref.read(listenSwitchProvider.notifier).state = true; }, child: const Text('开始监听') ) ], ); } }
补充:仅监听状态变化不更新UI
如果不需要在UI中展示Provider的值,只是要监听状态变化做逻辑处理,可以用ref.listen在点击时初始化监听:
class Example extends ConsumerWidget { const Example({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Column( children: [ Text("some text"), ElevatedButton( onPressed: () { // 点击后开始监听,后续状态变化都会触发回调 ref.listen(userNameProvider, (previous, next) { print('用户名更新为:$next'); // 这里处理状态变化后的业务逻辑 }); }, child: const Text('开始监听') ) ], ); } }
内容的提问来源于stack exchange,提问作者Saad
相关产品推荐
相关产品推荐

