Flutter使用image_gallery_saver存图UI卡顿,compute调用报错求助
问题描述
使用image_gallery_saver保存图片时,UI线程会根据图片大小出现不同程度的卡顿。尝试用compute创建新线程执行保存逻辑时,抛出以下错误:
在platform_channel.dart中,由以下代码抛出:
BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger;
异常信息:{_CastError} Null check operator used on a null value
当前使用的代码:
try { //CheckPermission if (await Permission.storage.request().isGranted) { final result = await SaveImageToKoi(post.fimgUrl!.url!); print(result); if (result != null) BotToast.showText(text: "Success"); else BotToast.showText(text: "Error"); } } catch (e) {} }, dynamic SaveImageToKoi (koi_url) async { print(koi_url); var response = await Dio().get( koi_url, options: Options(responseType: ResponseType.bytes)); final result = await ImageGallerySaver.saveImage( Uint8List.fromList(response.data), quality: 100); }
错误原因
compute会把任务放到独立的Dart隔离区(Isolate)执行,但image_gallery_saver底层依赖的平台通道(MethodChannel)只能在主隔离区使用——非主隔离区没有初始化ServicesBinding,导致ServicesBinding.instance为null,触发空检查错误。
UI卡顿的核心原因是:你把图片下载、数据转换、平台保存全放在了主线程,大图片的下载和字节转换操作会阻塞UI线程。
解决方案
拆分任务:将纯Dart实现的图片下载、字节转换逻辑放到compute中执行,平台保存操作(ImageGallerySaver.saveImage)留在主线程处理。既规避了隔离区调用平台通道的错误,又能让主线程不被耗时操作阻塞。
修改后的代码示例:
try { // 检查存储权限 if (await Permission.storage.request().isGranted) { // 将下载逻辑放到后台隔离区执行 final imageBytes = await compute(_downloadImageBytes, post.fimgUrl!.url!); if (imageBytes != null) { // 保存图片操作留在主线程执行 final result = await ImageGallerySaver.saveImage( imageBytes, quality: 100, ); print(result); BotToast.showText(text: result != null ? "保存成功" : "保存失败"); } else { BotToast.showText(text: "图片下载失败"); } } } catch (e) { print(e); BotToast.showText(text: "操作异常"); } }, // 纯Dart函数,仅负责下载图片并返回字节数据,用于在compute中执行 Uint8List? _downloadImageBytes(String koiUrl) async { try { print(koiUrl); var response = await Dio().get( koiUrl, options: Options(responseType: ResponseType.bytes), ); return Uint8List.fromList(response.data); } catch (e) { print(e); return null; } }
补充说明
compute仅支持执行纯Dart逻辑,不能包含任何原生插件调用,因为隔离区无法访问主隔离区的平台通信机制。- 拆分后,耗时的下载和字节转换在后台隔离区运行,主线程只处理权限检查、触发保存和用户提示,不会再出现UI卡顿。
内容的提问来源于stack exchange,提问作者Dr_Black
相关产品推荐
相关产品推荐

