Flutter中的流生成器被召回。我不知道为什么。我相信问题可能是我在流构建器中有一个bloc提供程序。我的流dataBloc.dataStream没有更改,导致streambuilder再次构建。不知道,我在做什么错。流构建器是否一次又一次构建我的窗口小部件,而流中没有任何更改。显然那是不对的!对吧?
Widget build(context) {
final DataBloc dataBloc = DataBlocProvider.of(context);
print("dropdown build called again");
// this doesn't print recursively so this is perfect.
// So my build is not getting called again.
return StreamBuilder(
stream: dataBloc.dataStream,
builder: (context, snapshot) {
//ToDo remove prints
print("dropdown ${snapshot.data}");
// there is no change in snapshot.data, however print is getting called recursively. This is bad and wrong
// so my stream builder is getting called again, and this is wrong
String key = dataElement.conditionalField;
String _valueArray = dataElement.conditionalValues.toString();
String conditionalValue =
_valueArray.substring(1, _valueArray.length - 1);
Map<String, String> dataMap = snapshot.hasData ? snapshot.data : {};
bool isVisible = true;
if (key != "" &&
dataMap.containsKey(key) &&
dataMap[key] == conditionalValue.toString()) {
isVisible = true;
} else if (key != "") {
isVisible = false;
}
return Visibility(
child: BlocDropDownProvider(
fieldName: dataElement.key,
dataBloc: dataBloc,
child: Card(
color: Colors.grey[100],
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
label,
new Container(
height: 8.0,
),
dropDown,
],
),
),
),
visible: isVisible? true:false,
);
控制台上的输出为:
I/flutter (14422): dropdown {idnumber: 10}
I/flutter (14422): dropdown {idnumber: 10}
答案 0 :(得分:0)
根据给出的详细信息,我无法真正以1:1的精度复制此问题。我遇到的类似情况是StreamBuilder
的更改再次调用ConnectionState
中的内部版本。
这是使用StreamBuilder发送HTTP请求的最小复制。这里的HTTP请求示例基于此Flutter Networking guide。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@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> {
final streamController = StreamController();
@override
void initState() {
super.initState();
fetchAlbum().then((response) => streamController.add(response));
}
@override
void dispose() {
super.dispose();
streamController.close();
}
@override
Widget build(BuildContext context) {
debugPrint('build');
return StreamBuilder(
stream: streamController.stream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
debugPrint('Stream $snapshot');
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: snapshot.hasData
? Text('Album ${snapshot.data.title}')
: Text('Waiting...'),
),
);
},
);
}
Future<Album> fetchAlbum() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/albums/1');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
}
class Album {
final int userId;
final int id;
final String title;
Album({this.userId, this.id, this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
再说一次,我建议不要太在意构建成本,只要构建中的Widget是可管理的即可。此doc中讨论了有关Flutter最佳做法的更多详细信息。