architecture – Flutter嵌套的StreamBuilders导致Bad状态:Stre
我正在尝试使用视频
Flutter / AngularDart – Code sharing,better together (DartConf 2018)中描述的BLoC模式构建Flutter应用程序
BLoC基本上是一个带有Sink输入和Stream输出的视图模型.在我的例子中它看起来有点像这样: class BLoC { // inputs Sink<String> inputTextChanges; Sink<Null> submitButtonClicks; // outputs Stream<bool> showLoading; Stream<bool> submitEnabled; } 我在层次结构根目录附近的小部件中定义了BLoC,并将其传递给它下面的小部件,包括嵌套的StreamBuilders.像这样: 顶级StreamBuilder监听BLoC上的showLoading流,以便它可以重建以显示重叠的进度微调器.底部StreamBuilder侦听submitEnabled流以启用/禁用按钮. 问题是每当showLoading流导致顶级StreamBuilder重建窗口小部件时,它也会重建嵌套窗口小部件.这本身就很好并且预期.但是,这会导致重新创建底部的StreamBuilder.当发生这种情况时,它会尝试重新订阅BLoC上的现有submitEnabled流,从而导致Bad状态:Stream已被监听 有没有办法在不创建所有输出BroadcastStream的情况下完成此操作? (我也有可能从根本上误解BLoC模式.) 下面的实际代码示例: import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; import 'dart:async'; void main() => runApp(BlocExampleApp()); class BlocExampleApp extends StatefulWidget { BlocExampleApp({Key key}) : super(key: key); @override _BlocExampleAppState createState() => _BlocExampleAppState(); } class _BlocExampleAppState extends State<BlocExampleApp> { Bloc bloc = Bloc(); @override Widget build(BuildContext context) => MaterialApp( home: Scaffold( appBar: AppBar(elevation: 0.0),body: new StreamBuilder<bool>( stream: bloc.showLoading,builder: (context,snapshot) => snapshot.data ? _overlayLoadingWidget(_buildContent(context)) : _buildContent(context) ) ),); Widget _buildContent(context) => Column( crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[ TextField( onChanged: bloc.inputTextChanges.add,),StreamBuilder<bool>( stream: bloc.submitEnabled,builder: ((context,snapshot) => MaterialButton( onPressed: snapshot.data ? () => bloc.submitClicks.add(null) : null,child: Text('Submit'),) ) ) ] ); Widget _overlayLoadingWidget(Widget content) => Stack( children: <Widget>[ content,Container( color: Colors.black54,Center(child: CircularProgressIndicator()),],); } class Bloc { final StreamController<String> _inputTextChanges = StreamController<String>(); final StreamController<Null> _submitClicks = StreamController(); // Inputs Sink<String> get inputTextChanges => _inputTextChanges.sink; Sink<Null> get submitClicks => _submitClicks.sink; // Outputs Stream<bool> get submitEnabled => Observable<String>(_inputTextChanges.stream) .distinct() .map(_isInputValid); Stream<bool> get showLoading => _submitClicks.stream.map((_) => true); bool _isInputValid(String input) => true; void dispose() { _inputTextChanges.close(); _submitClicks.close(); } } 解决方法
据我了解BLoC,您应该只有一个输出流连接到StreamBuilder.此输出流发出包含所有必需状态的模型.
你可以在这里看到它是如何完成的:https://github.com/ReactiveX/rxdart/blob/master/example/flutter/github_search/lib/github_search_widget.dart 如果需要组合多个流来生成模型(sowLoading和submitEnabled),则可以使用RxDart中的Observable.combineLatest将多个流合并为一个流.我使用这种方法,它的工作非常好. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |