Flutter Riverpod 2.0:如何通过用户输入手动向Stream Provider发送值
用Riverpod Stream Provider实现交互式Stream更新
你的核心问题在于当前的counterStream()只是一次性发射初始值的冷流,调用incStreamVal()更新counter后,流不会主动发射新值。要实现用户交互驱动的流更新,需要用StreamController创建热流,通过sink主动推送新值。
以下是修正后的完整实现:
1. 重构状态类,使用StreamController
import 'dart:async'; class CounterState1 { int counter; final StreamController<int> _controller; CounterState1(this.counter) : _controller = StreamController<int>.broadcast() { // 初始发射一次当前值,确保页面加载时显示初始状态 _controller.add(counter); } // 对外暴露供StreamProvider监听的stream Stream<int> get counterStream => _controller.stream; // 递增数值并向流推送新值 void incStreamVal() { counter++; _controller.add(counter); } // 销毁时关闭controller,避免内存泄漏 void dispose() { _controller.close(); } }
2. 配置Riverpod Providers
import 'package:flutter_riverpod/flutter_riverpod.dart'; // 提供CounterState1实例,管理其生命周期 final counterState1Provider = Provider<CounterState1>((ref) { final state = CounterState1(1); // Provider销毁时调用dispose关闭流控制器 ref.onDispose(() => state.dispose()); return state; }); // StreamProvider监听CounterState1的counterStream final streamCounterProvider = StreamProvider<int>((ref) { return ref.watch(counterState1Provider).counterStream; });
3. 更新Widget实现交互逻辑
class IncrementerView2 extends ConsumerWidget { const IncrementerView2({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final asyncVal = ref.watch(streamCounterProvider); return Scaffold( appBar: AppBar(title: const Text("Incrementer")), body: Center( child: asyncVal.when( data: (data) => Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text(data.toString(), style: const TextStyle(fontSize: 30)), const SizedBox(height: 20), ElevatedButton( onPressed: () { ref.read(counterState1Provider).incStreamVal(); }, child: const Text("inc First"), ), ], ), error: (error, stackTrace) => Text(error.toString()), loading: () => const CircularProgressIndicator(), ), ), ); } }
关键说明
- 使用
StreamController.broadcast()创建广播流,支持多个组件同时监听同一个StreamProvider。 - 通过
ref.onDispose()绑定流控制器的销毁逻辑,避免内存泄漏。 - 点击按钮时调用
incStreamVal(),通过_controller.add(counter)将新值推送到流中,StreamProvider会自动监听并触发UI更新。
内容的提问来源于stack exchange,提问作者MohaAmiry
相关产品推荐
相关产品推荐

