☰
Flutter-Notebook 实战:基于 multi_image_picker 实现本地相册多图选择与缩略图展示
2026/10/15 17:40:41 网站建设 项目流程
  • 示例工程
  • 移动开发

【免费下载链接】Flutter-Notebook

FlutterDemo合集,今天你fu了吗

项目地址:https://gitcode.com/gh_mirrors/fl/Flutter-Notebook
点击查看免费下载

导读

本文围绕 Flutter-Notebook 仓库中 load_multi_image 示例工程 展开,讲解如何在 Flutter 中调用multi_image_picker插件从系统相册批量选择图片,并借助Asset.thumbData与requestThumbnail()高效加载缩略图、以瀑布流式列表实时展示。读完本文,你将掌握该插件的依赖引入、平台权限配置、异步选图 API 的调用姿势,以及 Android minSdkVersion 兼容性问题的排查思路,可直接复用到自己的图片选择类 App 中。

工程概览与运行效果

load_multi_image是 Flutter-Notebook 众多 Flutter Demo 之一,工程结构为标准的 Flutter 应用布局:Dart 业务代码集中在 lib/ 下,Android 与 iOS 原生工程分别位于 android/ 和 ios/。

应用运行后的交互非常简单直观:

  • 首页是一个空列表,右下角悬浮着图片图标(Icons.image)的FloatingActionButton;
  • 点击悬浮按钮弹出系统相册选择器,用户可勾选多张图片;
  • 确认后回到 App,选中的图片会以网格列表形式逐张加载缩略图并展示。

依赖引入:在 pubspec.yaml 中声明插件

示例工程在 pubspec.yaml 中声明了核心依赖:

dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2 multi_image_picker: ^2.2.10

对应的 pubspec.lock 锁定实际解析版本为2.2.10(依赖来源为 pub.flutter-io.cn 镜像源)。需要注意的是,2.x版本的 API 形态与后来 4.x 分支(引入MultiImagePickerController的新架构)差异较大,若升级大版本,下方示例代码需同步改写。

选图主流程:MultiImagePicker.pickImages 调用解析

核心业务逻辑全部位于 lib/load_image_demo.dart,通过StatefulWidget维护选中图片列表。其选图方法完整代码如下:

List<Asset> images = List<Asset>(); String _error; Future<void> loadAssets() async { setState(() { images = List<Asset>(); }); List resultList; try { resultList = await MultiImagePicker.pickImages( maxImages: 300, ); } on PlatformException catch (e) { _error = e.message; } // If the widget was removed from the tree while the asynchronous platform // message was in flight, we want to discard the reply rather than calling // setState to update our non-existent appearance. if (!mounted) return; setState(() { images = resultList; if (_error == null) _error = 'No Error Dectected'; }); }

这段代码包含了几个值得注意的工程细节:

  • maxImages: 300:限制单次最多可选择 300 张图片。该参数是pickImages的核心配置,可根据产品需求调整(如相册分享场景可设为 9 张,批量上传场景可放宽)。
  • PlatformException捕获:插件底层走的是 MethodChannel 原生通道,用户在系统相册中取消选择、权限被拒或原生端抛错时,Dart 侧会收到PlatformException,因此必须用try/catch兜底,避免异常冒泡导致界面崩溃。
  • mounted检查:await挂起期间用户可能已退出页面,此时 widget 已从树中移除,直接调用setState会报错。通过if (!mounted) return;主动丢弃飞行中的异步回包,是 Flutter 异步编程的规范姿势。
  • 错误状态兜底:_error初始为null,成功回调后若仍为null则置为'No Error Dectected',避免 UI 层空指针判断。

选择完成后,返回结果被赋值为List<Asset>,Asset即multi_image_picker对单张系统图片的封装对象(导入自package:multi_image_picker/asset.dart)。

缩略图加载:thumbData 与 requestThumbnail 的分工

拿到Asset列表后,示例并未直接加载原图,而是采用"先取缩略图字节、按需异步放大"的两段式策略:

Widget builtImage(Asset asset) { if (asset.thumbData != null) { return Image.memory( asset.thumbData.buffer.asUint8List(), fit: BoxFit.cover, gaplessPlayback: true, ); } return Container(); } void _loadImage(Asset asset) async { await asset.requestThumbnail(300, 300); setState(() {}); }

逐行拆解其原理:

  1. asset.thumbData:插件在选图阶段已随Asset一并返回的缩略图字节缓存(ByteData类型)。由于thumbData可能为空,builtImage先做判空,为空时渲染占位Container()。
  2. Image.memory:将thumbData.buffer.asUint8List()转成Uint8List后直接以内存字节渲染,无需磁盘 I/O 与网络请求,是本地图片展示的最高效路径。fit: BoxFit.cover保证缩略图裁剪填充网格单元;gaplessPlayback: true在图片数据刷新时复用旧帧,避免闪烁。
  3. requestThumbnail(300, 300):在列表项构建时被调用,请求插件异步生成300x300尺寸的高清缩略图。返回后触发setState刷新该行,实现"先模糊占位、后高清呈现"的渐进式加载体验。

从工程结构看,这套"按需 requestThumbnail + setState 局部刷新"的方案避免了为列表中数百张图片一次性生成全尺寸缩略图的内存与性能开销,可以推断其设计意图是支撑大批量选图场景下的流畅滚动。

列表主体使用ListView.builder按需构建行,每行的itemBuilder中先调用_loadImage(images[index])再返回builtImage,保证每张图片的缩略图请求都在其行可见时才发起(见 lib/load_image_demo.dart):

body: ListView.builder( itemCount: images.length, itemBuilder: (context,index){ _loadImage(images[index]); return builtImage(images[index]); }), floatingActionButton: FloatingActionButton( onPressed: loadAssets, child: Icon(Icons.image), ),

平台权限与配置:Android minSdkVersion 19 兼容性详解

multi_image_picker属于原生插件,Android 端除在 AndroidManifest.xml 声明INTERNET、READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE三项权限外(其中读写外部存储权限对应相册图片访问),还需满足插件的 SDK 版本下限要求。

关联文档特别提示了本项目踩过的坑:

若出现 minSdk 版本导致编译失败,请修改 build.gradle 中 minSdk 版本为 19

对照 android/app/build.gradle 实际配置,示例工程的编译参数为:

android { compileSdkVersion 27 defaultConfig { applicationId "club.litavadaski.loadmultiimage" minSdkVersion 19 targetSdkVersion 27 ... } }

这里的minSdkVersion 19正是文档要求的取值。原因在于multi_image_picker 2.2.10的原生依赖要求 Android 4.4(API 19)及以上的系统 API 能力(如 ContentResolver 批量查询与缩略图生成接口),若项目默认的minSdkVersion低于 19(Flutter 早期模板默认为 16),编译阶段 Gradle 会报 manifest merger 或 dependency 冲突类错误。解决路径就是上面这句:将minSdkVersion提升到 19。同理,若插件后续版本要求更高,也只需同步上调该值。

需要说明的是:升级 minSdk 意味着放弃对更老 Android 版本设备(低于 4.4)的兼容,这在 Android 生态中早已是合理取舍。另外,compileSdkVersion与targetSdkVersion均为 27,与 2018 年前后的 Flutter 模板保持一致,若在更新的 Flutter 版本上运行本示例,需按新模板同步上调compileSdkVersion。

入口与原生宿主:main.dart 与 MainActivity

lib/main.dart 是应用入口,使用MaterialApp+ThemeData.dark()深色主题,home直接指向LoadImageDemo:

void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData.dark(), home: LoadImageDemo() ); } }

Android 宿主 MainActivity.java 继承FlutterActivity,并在onCreate中调用GeneratedPluginRegistrant.registerWith(this)完成插件注册——这正是multi_image_picker的 MethodChannel 能在 Dart 侧被调用的前提。

iOS 侧工程(ios/)为 Flutter 默认 Runner 模板,Podfile 通过解析.flutter-plugins自动链接插件 Pod。按 multi_image_picker 官方要求,iOS 实际运行前还需在 Info.plist 中补充NSPhotoLibraryUsageDescription相册权限描述文案,否则首次访问相册会被系统直接拒绝(本仓库示例的 Info.plist 未内置该键,读者自行运行前需手动添加)。

运行与验证

在 Flutter 环境就绪的前提下,进入示例工程目录即可运行(命令在当前仓库路径mecury_project/example/load_multi_image/下执行):

flutter pub get # 解析 multi_image_picker 依赖 flutter run # 连接真机或模拟器运行

仓库自带的 test/widget_test.dart 是一个基础冒烟测试:pumpWidget(new MyApp())构建应用后验证计数器初始为 0(该文件为 Flutter 模板默认测试,尚未针对选图流程编写用例),可用flutter test验证工程可正常构建编译。

小结

load_multi_image演示了一条完整可复用的本地多图选择技术链路:

  1. pubspec.yaml引入multi_image_picker ^2.2.10;
  2. Android 端配置minSdkVersion 19与存储权限,iOS 端补充相册权限描述;
  3. Dart 侧以MultiImagePicker.pickImages(maxImages: 300)异步选图,并用PlatformException捕获 +mounted检查保证健壮性;
  4. 用Asset.thumbData+requestThumbnail(300, 300)+Image.memory组合实现高性能缩略图渐进加载。

无论你是要做相册批量上传、多图消息发送还是图片整理工具,都可以直接以此为起点,将 load_image_demo.dart 中的选图逻辑与缩略图渲染模式抽取到自己的业务工程中。

  • 示例工程
  • 移动开发

【免费下载链接】Flutter-Notebook

FlutterDemo合集,今天你fu了吗

项目地址:https://gitcode.com/gh_mirrors/fl/Flutter-Notebook
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询