【发布时间】:2021-02-26 11:45:16
【问题描述】:
我有一个 StreamBuilder,我希望能够暂停和取消暂停,并且由于 StreamBuilder doesn't expose it's underlying StreamSubscription,我必须创建一个代理流来转发源流的元素,同时公开一个我可以暂停和取消暂停的 StreamSubscription。这迫使我将无状态小部件转换为有状态小部件,以便我可以访问 dispose 并关闭它的 StreamController。
我正在遵循didUpdateWidget 文档的说明:
在 initState 中,订阅对象。 如果更新的小部件配置需要替换对象,则在 didUpdateWidget 中取消订阅旧对象并订阅新对象。 在 dispose 中,取消订阅该对象。
每当用户输入新的搜索查询时,我都需要替换 Stream。每当接收到新流时,我的有状态小部件都会在 ChangeNotifier 中重新构建。
这是我的有状态小部件的相关部分:
final Stream<List<Entry>> _entryStream;
StreamController<List<Entry>> _entryStreamController;
StreamSubscription<List<Entry>> _entryStreamSubscription;
_EntryListState(this._entryStream);
void initStream() {
_entryStreamController?.close();
_entryStreamController = StreamController();
_entryStreamSubscription = _entryStream.listen((event) {
_entryStreamController.add(event);
}
)..onDone(() => _entryStreamController.close());
}
@override
void initState() {
initStream();
super.initState();
}
@override
void dispose() {
_entryStreamController?.close();
super.dispose();
}
@override
void didUpdateWidget(EntryList oldEntryList) {
// Initialize the stream only if it has changed
if (oldEntryList._entryStream != _entryStream) initStream();
super.didUpdateWidget(oldEntryList);
}
这是抛出 BadState 错误的行:
_entryStreamSubscription = _entryStream.listen((event) {
_entryStreamController.add(event);
}
这里是构建我的小部件的地方:
child: Consumer<SearchStringModel>(
builder: (context, searchStringModel, child) {
print('rebuilding with: ${searchStringModel.searchString}');
var entryStream = _getEntries(searchStringModel.searchString);
return EntryList(entryStream);
}
),
我不认为我特别了解 didUpdateWidget 并怀疑这就是这两个问题(不良状态和未更新)的来源?我还重新构建了有状态小部件,而不是仅仅修改它的状态,这有点令人困惑,但小部件旨在充当所有意图和目的的无状态小部件,因此更新它会很痛苦状态而不是重建。有什么建议吗?
【问题讨论】: