You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:00:08