【发布时间】:2019-06-20 01:16:41
【问题描述】:
我在以下层次结构中设置了我的小部件,以便在两个选项卡之间传递数据
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,
);
},
);
}
}
);
【问题讨论】: