flutter - StreamBuilder 和 Flutter 中的流问题(接收重复数据)

标签 flutter stream duplicates stream-builder sink

今天我遇到了流和 StreamBuilder 的问题。 问题如下: 如果您有多个 StreamBuilder 小部件监听同一个流,并且您将数据添加到它的接收器中,则该数据将通过流传出您拥有的 StreamBuilder 监听器的数量,换句话说: 如果您有一个 StreamController(或 BehaviorSubject),k 个 StreamBuilder 类型的小部件,并且您尝试执行 StreamController.sink.add(event),则此事件将通过流发出 k 次,每个 StreamBuilder 一个。 这是预期的行为吗(预期行为=输入一个事件并从另一端独立地听取一次事件,而与听众的数量无关)?我能够“修复”这种将几乎所有小部件树封装到一个 StreamBuilder 中的方法,但这不如第一种方法最佳,因为您正在渲染整个树而不是一些小节点小部件。 如果你想的话,我在这里留下了一些代码来测试它(这段代码是 flutter create project_name project 的修改)。 谢谢! (P.D:如果你只是在没有 StreamBuilder 的情况下收听流,这很有效,即:streamController.stream.listen..)

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:rxdart/subjects.dart';

class MyAppBloc with ChangeNotifier {
  int _currentIndex;
  BehaviorSubject<bool> _controller;

  MyAppBloc() {
    _currentIndex = 0;
    _controller = BehaviorSubject<bool>();
  }

  Stream<int> get currentIndex => _controller.stream.map<int>((event) {
        print('[event: $event]');
        _currentIndex++;
        return _currentIndex;
      });

  StreamSink<bool> get increment => _controller.sink;

  void close() {
    _controller.close();
  }
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_project/bloc/my_app_bloc.dart';

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;
  Widget leadingBuilder(MyAppBloc bloc) {
    return StreamBuilder<int>(
      initialData: 0,
      stream: bloc.currentIndex,
      builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
        print('[leadingBuilderSnapshot: $snapshot]');
        return Text(snapshot.data.toString());
      },
    );
  }

  StreamBuilder<int> counterBuilder(MyAppBloc bloc) {
    return StreamBuilder<int>(
      initialData: 0,
      stream: bloc.currentIndex,
      builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
        print('[counterBuilderSnapshot: $snapshot]');
        return Text(
          snapshot.data.toString(),
          style: Theme.of(context).textTheme.headline4,
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    print('[build]');
    final _bloc = Provider.of<MyAppBloc>(context);
    return Scaffold(
      appBar: AppBar(
        leading: Container(
          width: 30,
          height: 30,
          alignment: Alignment.center,
          child: leadingBuilder(_bloc),
        ),
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            StreamBuilder<int>(
              initialData: 0,
              stream: _bloc.currentIndex,
              builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                return Text('${snapshot.data}');
              },
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            counterBuilder(_bloc),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _bloc.increment.add(true),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

最佳答案

因为 currentIndex 是一个 getter 而你正在使用 map(),所以每次都会创建一个新的流 您调用 bloc.currentIndex 并且 StreamBuilder 将收听它。

所以在原始代码中,实际上有1个StreamControlller,和k个Streams。 (k:StreamBuilder 的数量)

要解决您的问题,您可以创建一个 eventController,并在一个 bloc 中监听它以执行您的逻辑。 (eventStream 只从 bloc 本身监听,它只会被创建一次)

例如:

class MyAppBloc {
  MyAppBloc() {
    _eventController.listen((event) {
      print('[event: $event]');
      _indexController.add(currentIndex.value + 1);
    });
  }

  final _indexController = BehaviorSubject<int>.seeded(0);
  final _eventController = PublishSubject<bool>();

  ValueStream<int> get currentIndex => _indexController.stream;
  StreamSink<bool> get increment => _eventController.sink;

  void close() {
    _indexController?.close();
    _eventController?.close();
  }
}

关于flutter - StreamBuilder 和 Flutter 中的流问题(接收重复数据),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63641258/

相关文章:

json - 如何将对象流式传输到 gzipped json?

javascript - 如何通过 API 将流数据发送到 Nuxt3 应用程序?

java - ArrayList 中的 "Duplicate"条目?

java - Android - 无需对象实例化即可避免重复

flutter - Flutter:动态文本字段显示相同的值吗?

flutter - ScanStreamTransformer 上的 NULL 累加器

dictionary - 如何将从cloud_firestore接收的数据转换为Map

Java FileOutputStream,将 double 据写入文件

r - 在 R 中的数据框中查找重复的行(基于 2 列)

flutter - 从模型将回调传递到 Flutter 中的 GestureDetector 的语法