gpt4 book ai didi

flutter - 在 BottomNavigationBar 选项卡之间传递 StreamBuilder => 错误状态 : Stream has already been listened to

转载 作者:行者123 更新时间:2023-12-03 04:33:58 25 4
gpt4 key购买 nike

我正在尝试将 Stream 从一个选项卡传递到另一个选项卡,但是当我在 home.dart 中回来时
选项卡更改时我可以关闭/销毁流吗?
当应用程序运行时,数据被正确获取并且一切都很好。问题只有在我更改选项卡时才会出现。
数据存储到 Firestore 数据库中。
我收到此错误:

Bad state: Stream has already been listened to


这是我的家.dart
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
Home createState() => Home();
}

class Home extends State<HomePage> {
int _currentIndex;
var _tabs = [];

List<Company> currentCompaniesList = List();
StreamController<List<Company>> _streamController;
Stream<List<Company>> companiesStream;

_getData() async {
_companyService
.getCompanies()
.then((value) => _streamController.sink.add(value));
}

@override
void initState() {
super.initState();
_currentIndex = 0;

_streamController = StreamController<List<Company>>();

_getData();
companiesStream = _streamController.stream;
}
}


@override
Widget build(BuildContext context) {
_tabs = [
CompanyTab(stream: companiesStream),
MapTab(),
Center(child: Text('Profile')),
Center(child: Text('Settings')),
];

return Scaffold(
...
actions: ...,
body: _tabs[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
backgroundColor: BACKGROUND_COLOR,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
)
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
这是我的 CompanyTab.dart
class CompanyTab extends StatefulWidget {
Stream stream;

CompanyTab({Key key, this.stream}) : super(key: key);

@override
_CompanyTabState createState() => _CompanyTabState(stream);
}

class _CompanyTabState extends State<CompanyTab> {
Stream stream;

_CompanyTabState(this.stream);

@override
void initState() {
super.initState();
}

StreamBuilder companyList() {
return StreamBuilder<List<Company>>(
initialData: [],
stream: stream,
builder: (BuildContext context, AsyncSnapshot<List<Company>> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}

if (snapshot.connectionState == ConnectionState.waiting ||
snapshot.connectionState == ConnectionState.none ||
snapshot.data == null) {
return LoadingWidget();
} else {
return ListView.builder(
padding: const EdgeInsets.all(10),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Company company = snapshot.data.elementAt(index);
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 1.0, horizontal: 4.0),
child: Card(
child: ListTile(
onTap: () {},
title: Text(company.name),
...
),
),
),
);
});
}
});
}

@override
Widget build(BuildContext context) {
return Center(
child: Container(
child: companyList(),
),
);
}
}

最佳答案

这是关于小部件生命周期的。我可以建议你两个选择。
1. 将 _streamController 和 _getData() 方法移至 _CompanyTabState。
默认 BottomNavigationBar当你离开时破坏标签
一个,当你回到它时再次初始化它。如果需要
您需要移动的行为_streamController_getData()方法入_CompanyTabState .别忘了打电话_streamController.close()里面 dispose()的方法_CompanyTabState , 这一点很重要。 _companyService
注入(inject)_CompanyTabState .这是一个生命周期的问题。
应该像这样工作:

...
class _CompanyTabState extends State<CompanyTab> {
final _streamController = StreamController<List<Company>>();
final CompanyService _companyService;

_CompanyTabState(this._companyService);

@override
void initState() {
super.initState();
_getData();
}

StreamBuilder companyList() {
return StreamBuilder<List<Company>>(
initialData: [],
stream: _streamController.stream,
builder: (BuildContext context, AsyncSnapshot<List<Company>> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}

if (snapshot.connectionState == ConnectionState.waiting ||
snapshot.connectionState == ConnectionState.none ||
snapshot.data == null) {
return LoadingWidget();
} else {
return ListView.builder(
padding: const EdgeInsets.all(10),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Company company = snapshot.data.elementAt(index);
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 1.0, horizontal: 4.0),
child: Card(
child: ListTile(
onTap: () {},
title: Text(company.name),
...
),
),
),
);
});
}
});
}

@override
Widget build(BuildContext context) {
return Center(
child: Container(
child: companyList(),
),
);
}

@override
void dispose() {
super.dispose();
_streamController.close();
}

void _getData() {
_companyService
.getCompanies()
.then((value) => _streamController.sink.add(value));
}
}

2.使用IndexedStack
当您离开选项卡时,您可以保存选项卡的状态和小部件数据(如滚动偏移、输入的文本等)。这是类似于 iOS UITabBarController 的行为。使用 IndexedStack为达到这个:
...
return Scaffold(
...
actions: ...,
body: IndexedStack(
children: _tabs,
index: _currentIndex,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
backgroundColor: BACKGROUND_COLOR,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
),
BottomNavigationBarItem(
...
)
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
使用什么选项取决于您,如果您愿意,可以同时使用。但我强烈建议将 _streamController 移动到 _CompanyTabState,因为它们的生命周期应该相同。

关于flutter - 在 BottomNavigationBar 选项卡之间传递 StreamBuilder => 错误状态 : Stream has already been listened to,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64441674/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com