如何在Flutter函数执行完成后显示SnackBar?
修复SnackBar提前显示的问题
问题根源
downloadProductsList函数中,fileRef.writeToFile(file)是异步操作,但未使用await等待其完成,导致函数在所有下载任务启动后立即返回,而非等待全部完成。- 按钮的
onPressed回调未标记为async,原代码中使用await会触发语法错误。 - 显示SnackBar无需调用
setState,该部分代码属于冗余操作。
修复步骤
1. 修复downloadProductsList函数
可选择以下两种方式之一:
方式一:串行下载(逐个等待文件完成)
确保每个文件下载完成后再处理下一个:
downloadProductsList() async { final storageRef = FirebaseStorage.instance.ref(); final customers = ['A', 'B', 'C', 'D', 'E', 'F']; final baseDir = await getApplicationDocumentsDirectory(); String path = "${baseDir.path}/assets"; for (int i = 0; i < customers.length; i++) { final filePath = "$path/${customers[i]}.csv"; final file = await File(filePath).create(recursive: true); final fileRef = storageRef.child("assets/${customers[i]}.csv"); // 加上await,等待当前文件下载完成 await fileRef .writeToFile(file) .whenComplete(() => print('downloaded ${customers[i]}.csv')); } }
方式二:并行下载(同时处理所有文件,效率更高)
收集所有下载任务,等待全部完成:
downloadProductsList() async { final storageRef = FirebaseStorage.instance.ref(); final customers = ['A', 'B', 'C', 'D', 'E', 'F']; final baseDir = await getApplicationDocumentsDirectory(); String path = "${baseDir.path}/assets"; List<Future> downloadTasks = []; for (int i = 0; i < customers.length; i++) { final filePath = "$path/${customers[i]}.csv"; final file = await File(filePath).create(recursive: true); final fileRef = storageRef.child("assets/${customers[i]}.csv"); // 将每个下载任务加入列表 downloadTasks.add( fileRef .writeToFile(file) .whenComplete(() => print('downloaded ${customers[i]}.csv')) ); } // 等待所有下载任务完成 await Future.wait(downloadTasks); }
2. 修复ElevatedButton代码
添加async标记,移除多余的setState:
ElevatedButton( onPressed: () async { await downloadProductsList(); final snackbar = SnackBar(content: Text('Download complete!'), duration: Duration(seconds: 2)); ScaffoldMessenger.of(context).showSnackBar(snackbar); }, )
修改完成后,SnackBar会在所有文件下载完成后才显示。
内容的提问来源于stack exchange,提问作者Safwan Parkar
相关产品推荐
相关产品推荐

