Flutter中StreamBuilder销毁重建后停止重绘问题排查
问题:StreamBuilder接收数据但不触发Widget重绘
项目结构
我有一个使用StreamBuilder监听并渲染列表的Widget(已省略无关细节):
class CloseUsersFromStream extends StatelessWidget { final Stream<List<User>> _stream; const CloseUsersFromStream(this._stream); @override Widget build(BuildContext context) { return StreamBuilder<List<User>>( stream: _stream, builder: _buildWidgetFromSnapshot, ); } Widget _buildWidgetFromSnapshot(_, AsyncSnapshot<List<User>> snapshot) { if (_snapshotHasLoaded(snapshot)) { return UsersButtonsList(snapshot.data!); } else { return const Center(child: CircularProgressIndicator()); } } bool _snapshotHasLoaded(AsyncSnapshot<List<User>> snapshot) { return snapshot.hasData; } }
其父Widget代码如下:
class CloseUsersScreen extends StatefulWidget { final ICloseUsersService _closeUsersService; const CloseUsersScreen(this._closeUsersService); @override State<CloseUsersScreen> createState() => _CloseUsersScreenState(); } class _CloseUsersScreenState extends State<CloseUsersScreen> { late final Stream<List<User>> _closeUsersStream; @override void initState() { _initializeStream(context); super.initState(); } @override void dispose(){ _closeStream(); super.dispose(); } @override Widget build(BuildContext context) { return SafeArea( child: Column( children: [ //... CloseUsersFromStream(_closeUsersStream), ], ), ); } void _initializeStream(BuildContext context) { _closeUsersStream = widget._closeUsersService.openCloseUsersSubscription(context); } void _closeStream(){ widget._closeUsersService.closeCloseUsersSubscription(); } }
问题描述
有时,StreamBuilder在流产生新事件时不会重建Widget。调试确认流运行正常,StreamBuilder也能正确接收数据(调试器会停在return UsersButtonsList(snapshot.data!);行,且snapshot.data为预期值),但Widget并未按预期重绘。目前尚未明确问题触发规律,推测可能与特定条件下销毁StreamBuilder有关(无报错信息)。此外,项目中另一个StreamBuilder也出现同样问题。
已尝试的解决方案
- 自定义StreamBuilder:自行实现CustomStreamBuilder,问题依旧,调试显示代码执行但Widget不重绘。
- 使用ValueListenableBuilder:配合MyStreamNotifier实现,调试器走到
notifyListeners()但未触发builder函数。 - 添加UniqueKey:给StreamBuilder添加UniqueKey,问题未解决。
- 延迟销毁流:延迟1秒关闭流,问题依旧。
- 强制更新:将StreamBuilder改为StatefulWidget并在initState中调用setState,无效。
- 延迟初始化StreamBuilder:直到流初始化完成再渲染StreamBuilder,无效。
- 替换子Widget:将子Widget替换为简单Text,问题仍存在。
复现步骤
- 后端:克隆仓库,执行
docker compose up启动服务。 - 前端:克隆仓库,修改
lib/config/config.dart中的serverURL为本地IP。 - 操作流程:注册账号→进入第二屏点击“Cerrar sesión”→登录同一账号→再次进入第二屏→返回主屏幕,问题大概率出现(可能需重复1-2次)。
内容的提问来源于stack exchange,提问作者Lucas Tomic
相关产品推荐
相关产品推荐

