使用share_plus时,如何等待数据加载完成后触发文件分享?
问题分析与解决方案
你的核心问题是分享操作被过早触发(甚至在文件未加载完成时就执行),而且原代码中直接使用snapshot.data!会在数据未就绪时抛出空指针异常。下面是具体的修正思路和代码实现:
原代码的核心问题
- 每次
FutureBuilder的builder回调触发时(包括初始状态、加载中),都会执行Share.shareXFiles,导致重复分享甚至崩溃。 - 没有判断
snapshot.hasData就直接取data,空指针风险极高。
方案一:先加载再分享(简洁版)
先弹出加载模态框,等待文件加载完成后关闭模态框再执行分享,逻辑清晰且避免重复触发:
Future<void> share(BuildContext context) async { // 先弹出加载模态框 showModalBottomSheet( context: context, builder: (context) { return SizedBox( height: 200, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Text("Preparing sharing…"), SizedBox(height: 16), CircularProgressIndicator(), ], ), ), ); }, ); try { // 等待视频文件加载完成 final fileUrl = await Video.videoUrl(videoUrl!); final file = XFile(fileUrl); // 关闭加载模态框 Navigator.of(context).pop(); // 仅在文件就绪后执行分享 await Share.shareXFiles( [file], text: "Don't miss this out! Only on Shokaze", ); } catch (e) { // 加载/分享失败时关闭模态框,可添加错误提示 Navigator.of(context).pop(); // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("分享失败:$e"))); } }
方案二:在模态框内切换状态(带分享中提示)
如果需要在模态框内显示"分享中"状态,可以用StatefulBuilder维护状态,确保分享仅执行一次:
Future<void> share(BuildContext context) async { showModalBottomSheet( context: context, builder: (context) { return StatefulBuilder( builder: (context, setState) { bool isPreparing = true; // 延迟执行异步逻辑,避免阻塞UI构建 WidgetsBinding.instance.addPostFrameCallback((_) async { try { // 加载文件 final fileUrl = await Video.videoUrl(videoUrl!); final file = XFile(fileUrl); // 更新状态为"分享中" setState(() { isPreparing = false; }); // 执行分享 await Share.shareXFiles( [file], text: "Don't miss this out! Only on Shokaze", ); // 分享完成后关闭模态框 Navigator.of(context).pop(); } catch (e) { Navigator.of(context).pop(); // 错误处理 } }); return SizedBox( height: 200, child: Center( child: isPreparing ? Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Text("Preparing sharing…"), SizedBox(height: 16), CircularProgressIndicator(), ], ) : const Text("Sharing…"), ), ); }, ); }, ); }
关键优化点
- 确保分享仅在数据就绪后执行:通过
await或Future.then等待文件加载完成,再触发分享操作。 - 避免重复触发:不再在
FutureBuilder的builder中直接调用分享,而是将分享逻辑放在异步回调内。 - 异常处理:添加
try-catch捕获加载或分享过程中的错误,避免程序崩溃。
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

