dart - 重新打开使用 StreamBuilder 的 ExpansionTile 时出现错误的流状态
问题描述
第一次打开ExpansionTitle,一切都很好。在缩小和扩大它之后,我收到了一个“坏状态”流已经听过,错误。我尝试将流作为广播返回,但在最小化并重新打开后,快照为空。我不太确定将 ExpansionTitle 与流一起使用的正确技术是什么。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
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> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: StreamBuilder(
stream: _genres(),
builder:
(BuildContext context, AsyncSnapshot<List<String>> snapshot) {
print("snap: ${snapshot.data}");
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ExpansionTile(
title: Text(snapshot.data[index]),
children: <Widget>[
StreamBuilder(
stream: _moviemap(index + 1),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData)
return Text('No data');
List<Widget> items = [];
for(String name in snapshot.data) {
items.add(
ListTile(
title: Text(name),
)
);
}
return Column(children: items,);
},
),
],
);
});
} else {
return Container();
}
}),
),
);
}
Stream<List<String>> _genres() async* {
yield ['Horror', 'Comedy', 'Drama'];
}
Stream<List<String>> _moviemap(int which) async* {
if (which == 1) {
yield ['Saw', 'Scary Movie'];
} else if (which == 2) {
yield ['Grown ups', 'Grown ups 2', 'Paul Blart'];
} else {
yield ['Green Onions', 'Spring Breakers'];
}
}
}
解决方案
是因为以下几个原因。
StreamBuilder
从's到 .永久监听相同的流(_moviemap
在这种情况下)。StreamBuilder
initState()
dispose()
- 打开和关闭时
ExpansionTile
,它会重建children
新的StreamBuilder
. 并StreamBuilder
尝试倾听_moviemap
。那个时候老的StreamBuilder
还没有完成dispose()。 - 同一个 stream(
_moviemap
) 不允许多次收听。 - 所以崩溃了。
所以你应该交换StreamBuilder
' 位置和ExpansionTile
' 位置来监听 stream( _moviemap
) 一次。祝你好运!!
示例代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
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> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: StreamBuilder(
stream: _genres(),
builder:
(BuildContext context, AsyncSnapshot<List<String>> snapshot) {
print("snap: ${snapshot.data}");
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
final title = snapshot.data[index];
return StreamBuilder(
stream: _moviemap(index + 1),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) return Text('No data');
List<Widget> items = [];
for (String name in snapshot.data) {
items.add(ListTile(
title: Text(name),
));
}
return ExpansionTile(
title: Text(title),
children: <Widget>[
Column(
children: items,
),
],
);
},
);
},
);
} else {
return Container();
}
}),
),
);
}
Stream<List<String>> _genres() async* {
yield ['Horror', 'Comedy', 'Drama'];
}
Stream<List<String>> _moviemap(int which) async* {
if (which == 1) {
yield ['Saw', 'Scary Movie'];
} else if (which == 2) {
yield ['Grown ups', 'Grown ups 2', 'Paul Blart'];
} else {
yield ['Green Onions', 'Spring Breakers'];
}
}
}
推荐阅读
- asp.net - 在模板字段中使用本地资源
- c++ - 如何在 qt for windows 中使用 QAxObject 创建 docx 和 doc 文件?
- powerbi - PowerBi 测量的不可理解的结果
- python - url 在表单操作中不匹配(python django)
- python - 时间序列预测:分析
- html - CSS 不等 div 框
- vuetify.js - 添加 vuetify 时,纱线中的 -D 选项是什么
- google-cloud-platform - 如何在 Google BigQuery 中设置用户的查询配额
- symfony - Symfony | liipimaginebundle : 显示或转换 heic 文件
- asp.net-core - 未找到安全令牌签名密钥异常 IDX10501 无法匹配密钥孩子