我在以下层次结构中设置了小部件,以便在两个标签之间传递数据
DataShareWidget
TabBarView
InputManagment
InfiniteListView
DataShareWidget扩展了InheritedWidget并包含ShareData类,该类具有一个StreamController来发送和接收数据。
但是在接收端(InfiniteListView选项卡)正在获取重复数据。
在进入流之前,我已经从InputManagment中打印出原始数据,但是似乎没有任何重复的数据,因此流中一定有东西。
这是主文件中的相关代码
class ShareData {
final StreamController _streamController = StreamController.broadcast();
Stream get stream => _streamController.stream;
Sink get sink => _streamController.sink;
}
class DataShareWidget extends InheritedWidget {
final ShareData data;
DataShareWidget({
Key key,
@required Widget child,
}) :assert(child != null),
data = ShareData(),
super(key: key, child: child);
static ShareData of (BuildContext context) => (context.inheritFromWidgetOfExactType(DataShareWidget) as DataShareWidget).data;
@override
bool updateShouldNotify(DataShareWidget old) => false;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("MyApp"),
bottom: TabBar(
tabs: Tabs,
controller: _tabController,
),
),
body: DataShareWidget(
child: TabBarView(
controller: _tabController,
children: [
InputManagment(),
InfiniteListView(),
],
),
),
);
}
在数据管理文件中,我有这行代码来添加数据
DataShareWidget.of(context).sink.add(inputData);
这是InfiniteListView的代码
class _InfiniteScrollListViewState extends State<InfiniteScrollListView> with AutomaticKeepAliveClientMixin<InfiniteScrollListView>{
@override
bool get wantKeepAlive => true;
ScrollController _scrollController = ScrollController();
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
var _listViewData = new List();
_dataFormat(data){
var time = DateFormat('kk:mm:ss').format(DateTime.now());
var timeStampedData = time.toString() + "| " + data;
setState(() {_listViewData.add(timeStampedData); });
}
@override
Widget build(BuildContext context) {
DataShareWidget.of(context).stream.listen((data) => _dataFormat(data));
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
itemBuilder: (context, index) {
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
}
编辑:根据@jamesdlin的建议,我已经使用StreamBuilder重构了代码,并且看来已经解决了问题,这是下面的更新代码。
_dataFormat(data){
var time = DateFormat('kk:mm:ss').format(DateTime.now());
var timeStampedData = time.toString() + "| " + data;
_listViewData.add(timeStampedData);
}
@override
Widget build(BuildContext context) {
//_scrollToBottom();
return StreamBuilder(
stream: DataShareWidget.of(context).stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){ return Text(snapshot.error);}
if(snapshot.hasData){
_dataFormat(snapshot.data);
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
itemBuilder: (context, index) {
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
}
);
答案 0 :(得分:0)
每次调用listen
时,您都会在Stream
上调用_InfiniteScrollListViewState.build
。这将导致您的回调被多次调用。您应该只听一次Stream
。
您也许还应该考虑使用StreamBuilder
小部件。