Flutter StreamBuilder在LayoutBuilder中时颤振无限循环
因此,我正在使用所述的布局生成器制作一个页面 在LayoutBuilder中,我放置了一个StreamBuilder,其中包含一个TextField,由bloc类SignupFormBloc提供支持。流是一个行为主体 当有人在输入中放入某些内容时,它会触发onChanged函数,它是我的流的接收器。因此,我在流中添加该值,然后在StreamTransformer中传递该值以验证该值,然后让StreamBuilder再次构建文本字段,并显示一条错误消息(如果值无效) 这是问题的开始 当我点击文本字段并输入一些内容时,它会启动一个无限循环,如下所示:Flutter StreamBuilder在LayoutBuilder中时颤振无限循环,flutter,reactivex,bloc,rxdart,Flutter,Reactivex,Bloc,Rxdart,因此,我正在使用所述的布局生成器制作一个页面 在LayoutBuilder中,我放置了一个StreamBuilder,其中包含一个TextField,由bloc类SignupFormBloc提供支持。流是一个行为主体 当有人在输入中放入某些内容时,它会触发onChanged函数,它是我的流的接收器。因此,我在流中添加该值,然后在StreamTransformer中传递该值以验证该值,然后让StreamBuilder再次构建文本字段,并显示一条错误消息(如果值无效) 这是问题的开始 当我点击文本字
- StreamBuilder会在流中看到新值
- StreamBuilder尝试重新生成TextField
- 这是如何触发LayoutBuilder函数的
- LayoutBuilder函数再次构建StreamBuilder
- StreamBuilder在流中查找值(因为BehaviorSubject)
- 所有的一切都从一个无休止的循环中的第一个牛头开始
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SignupFormBloc _signupFormBloc;
@override
void initState() {
super.initState();
_signupFormBloc = SignupFormBloc();
}
@override
Widget build(BuildContext context) {
print('Build Run!!!!!');
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
print('Layout Builder!!!');
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: StreamBuilder<String>(
stream: _signupFormBloc.emailStream,
builder: (context, AsyncSnapshot<String> snapshot) {
return TextField(
onChanged: _signupFormBloc.onEmailChange,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Email',
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 18),
filled: true,
fillColor: Colors.white,
errorText: snapshot.error,
border: new OutlineInputBorder(
borderSide: BorderSide.none
),
),
);
}
),
),
),
);
},
)
);
}
@override
void dispose() {
_signupFormBloc?.dispose();
super.dispose();
}
}
class SignupFormBloc {
///
/// StreamControllers
///
BehaviorSubject<String> _emailController = BehaviorSubject<String>();
///
/// Stream with Validators
///
Observable<String> get emailStream => _emailController.stream.transform(StreamTransformer<String,String>.fromHandlers(handleData: (email, sink){
final RegExp emailExp = new RegExp(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$");
if (!emailExp.hasMatch(email) || email.isEmpty){
print('has error');
sink.addError('Email format is invalid');
} else {
sink.add(email);
}
}));
///
/// Sinks
///
Function(String) get onEmailChange => _emailController.sink.add;
void dispose() {
_emailController.close();
}
}
导入'dart:async';
进口“包装:颤振/材料.省道”;
导入“包:rxdart/rxdart.dart”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
SignupFormBloc\u SignupFormBloc;
@凌驾
void initState(){
super.initState();
_signupFormBloc=signupFormBloc();
}
@凌驾
小部件构建(构建上下文){
打印('Build Run!!!!!');
返回脚手架(
appBar:appBar(
标题:文本(widget.title),
),
正文:布局生成器(
生成器:(BuildContext上下文,BoxConstraints视口Constraints){
打印('Layout Builder!!!');
返回SingleChildScrollView(
子:约束框(
约束:BoxConstraints(
minHeight:viewportConstraints.maxHeight,
),
孩子:内在的(
孩子:StreamBuilder(
流:_signupFormBloc.emailStream,
生成器:(上下文,异步快照){
返回文本字段(
onChanged:\u signupFormBloc.onEmailChange,
键盘类型:TextInputType.emailAddress,
装饰:输入装饰(
hintText:“电子邮件”,
contentPadding:const EdgeInsets.对称(水平:15,垂直:18),
是的,
fillColor:Colors.white,
errorText:snapshot.error,
边框:新大纲输入边框(
borderSide:borderSide.none
),
),
);
}
),
),
),
);
},
)
);
}
@凌驾
无效处置(){
_signupFormBloc?.dispose();
super.dispose();
}
}
类注册FormBloc{
///
///流量控制器
///
BehaviorSubject_emailController=BehaviorSubject();
///
///验证流
///
Observable get emailStream=>\u emailController.stream.transform(StreamTransformer.fromHandlers)(handleData:(电子邮件,接收器){
最终RegExp emailExp=新的RegExp(r“^[a-zA-Z0-9+-]+@[a-zA-Z0-9-]+\[a-zA-Z0-9-]+$”;
如果(!emailExp.hasMatch(email)| | email.isEmpty){
打印('有错误');
sink.addError('电子邮件格式无效');
}否则{
添加(电子邮件);
}
}));
///
///下沉
///
函数(字符串)get-onEmailChange=>\u-emailController.sink.add;
无效处置(){
_emailController.close();
}
}
发生这种情况是因为误用了流
罪魁祸首是这样的:
Observable<String> get emailStream => _emailController.stream.transform(...);
先生,你是个英雄!集团式和反应式编程是一种非常棘手的模式。谢谢。
class MyBloc {
StreamController _someController;
Stream foo;
MyBloc() {
foo = _someController.stream.transform(...);
}
}