Flutter跨类更新LinearPercentIndicator百分比值的问题
问题解决指南
一、直接调用setState报错的原因及解决
报错提示setState() called in constructor: _SendtoLGState#48306(lifecycle state: created, no widget, not mounted),本质是State对象还未挂载到Widget树时就调用了setState。State生命周期中,只有当mounted属性为true(即Widget已插入树中)时,才能安全调用setState。
若坚持用这种方式,需先判断挂载状态:
// 在SendtoLG的State类中 void _loader(int progress) { if (mounted) { // 先检查是否已挂载 setState(() { // 此处更新进度值 }); } }
但更推荐使用ValueNotifier方案,避免直接操作State带来的耦合问题。
二、ValueNotifier进度条不更新的核心问题及修复
进度条停留在0,大概率是监听的ValueNotifier和上传时更新的不是同一个实例,导致监听的对象从未收到更新通知。
修复步骤:
- 明确ValueNotifier的类型(避免类型歧义):
class LGConnection { // 明确指定为int类型的ValueNotifier final ValueNotifier<int> progressNotifier = ValueNotifier(0); Future<void> uploadToLG(String localPath, String projectname) async { dynamic credencials = await _getCredentials(); // ... 其他前置代码 await client.connectSFTP(); await client.sftpUpload( path: localPath, toPath: '/var/www/html', callback: (progress) { print('Sent $progress'); // 直接赋值int类型进度值 progressNotifier.value = progress; }, ); await client.execute( 'echo "flytoview=${flyto.generateLinearString()}" > /tmp/query.txt'); } }
- 保证LGConnection实例唯一:
不要使用全局变量,而是在SendtoLG的State中持有同一个实例,确保上传和监听操作的是同一个对象:
class _SendtoLGState extends State<SendtoLG> { // 在State内部创建LGConnection实例 final LGConnection lgConnection = LGConnection(); // 触发上传的方法 void startUpload() async { await lgConnection.uploadToLG('你的本地文件路径', '项目名称'); } @override Widget build(BuildContext context) { return ValueListenableBuilder<int>( // 监听当前State内实例的progressNotifier valueListenable: lgConnection.progressNotifier, builder: (context, progress, child) { return LinearPercentIndicator( animation: true, lineHeight: 68.0, // 直接用int转double,避免字符串解析的风险 percent: progress / 100, center: Text( '$progress%', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black, fontSize: 40.0, ), ), barRadius: const Radius.circular(40), progressColor: Colors.greenAccent, ); }, ); } }
- 验证回调是否正常触发:
检查控制台是否输出Sent $progress的日志,如果没有输出,说明sftpUpload的回调未正常执行,需排查上传库的使用逻辑。
额外注意事项
- 上传完成后可手动重置进度值:
lgConnection.progressNotifier.value = 0;,避免下次上传时进度条从上次位置开始。 - 若需多页面共享上传进度,可将LGConnection设计为单例,或使用Provider等轻量状态管理工具,但单例需注意内存泄漏问题。
内容的提问来源于stack exchange,提问作者Yash Raj Bharti
相关产品推荐
相关产品推荐

