image_picker 在 Linux 上的落地:image_picker_linux 联邦插件实现与使用指南
【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages
image_picker_linux是 Flutter 官方维护的image_picker在 Linux 桌面平台上的实现包,属于典型的 endorsed(背书)联邦插件:应用层无需在pubspec.yaml中显式声明它,只要使用image_picker/file_selector就会自动被带入。本文基于仓库内该包的 README.md 与其源码实现,讲解它的架构原理、能力边界、cameraDelegate相机委托机制以及实际接入方式,帮助你在 Linux 桌面应用中快速、正确地完成图片与视频的选择功能。
包定位:Linux 平台的 image_picker 实现
image_picker_linux的定义位于 pubspec.yaml:
name: image_picker_linux description: Linux platform implementation of image_picker version: 0.2.2 environment: sdk: ^3.10.0 flutter: ">=3.38.0" flutter: plugin: implements: image_picker platforms: linux: dartPluginClass: ImagePickerLinux dependencies: file_selector_linux: ^0.9.1+3 file_selector_platform_interface: ^2.2.0 image_picker_platform_interface: ^2.11.0关键信息有三点:
- 它通过
implements: image_picker声明自己是image_picker的 Linux 平台实现,并在linux平台注册dartPluginClass: ImagePickerLinux; - 它的实现完全基于
file_selector_linux(文件选择对话框)与image_picker_platform_interface(平台接口定义),自身不包含任何原生 C/C++ 代码; - 版本要求为 Dart SDK ^3.10.0、Flutter >=3.38.0(当前仓库 CHANGELOG 中 "NEXT" 一节标注的升级项)。
从源码结构看,该包只有一个入口文件 lib/image_picker_linux.dart,核心类ImagePickerLinux继承自CameraDelegatingImagePickerPlatform,并通过静态方法注册为平台默认实例:
class ImagePickerLinux extends CameraDelegatingImagePickerPlatform { /// The file selector used to prompt the user to select images or videos. @visibleForTesting static FileSelectorPlatform fileSelector = FileSelectorLinux(); /// Registers this class as the default instance of [ImagePickerPlatform]. static void registerWith() { ImagePickerPlatform.instance = ImagePickerLinux(); } // ... }这段代码印证了 README 中“Linux 实现本质上是 file_selector 的封装”这一结论:fileSelector字段持有FileSelectorLinux()实例,所有相册(gallery)来源的选择操作都会转发给它。
使用方式:endorsed 插件的两种接入路径
README 的 Usage 部分明确了这是 endorsed(背书)插件,这意味着:
- 常规使用无需在
pubspec.yaml添加依赖。只要你的应用依赖了image_picker(或file_selector),Flutter 工具链会依据联邦插件注册表自动把image_picker_linux带入 Linux 构建,无需手工声明,也无需写任何平台注册代码。这也是应用层推荐的唯一用法。 - 若你想直接使用该包的 API(例如在测试中注入
ImagePickerLinux或替换fileSelector),则应像普通依赖一样显式加入:
dependencies: image_picker_linux: ^0.2.2两种方式下,应用层代码都保持不变,仍然使用image_picker的统一 API:
final picker = ImagePicker(); // 从相册选择一张图片 final XFile? image = await picker.pickImage(source: ImageSource.gallery); // 选择一段视频 final XFile? video = await picker.pickVideo(source: ImageSource.gallery);能力边界:README 明示的限制与源码印证
README 用专门一节列出了 Linux 实现的 Limitations,这是接入前必须了解的能力边界,逐条与源码对应如下。
ImageSource.camera 默认不支持
ImageSource.camerais not supported unless acameraDelegateis set.
在 getImageFromSource 与 getVideo 中,ImageSource.camera分支直接调用super(即CameraDelegatingImagePickerPlatform的默认实现),由平台接口在未设置cameraDelegate时抛出StateError。源码注释明确写道:
// If source is `ImageSource.camera`, a `StateError` will be thrown // unless a [cameraDelegate] is set.原因正如image_picker主 README 所述:与 Android/iOS 不同,Linux 桌面没有系统提供的拍照 UI,因此默认无法调用相机。测试用例 image_picker_linux_test.dart 同时覆盖了两种行为:设置FakeCameraDelegate后 camera 来源正常返回文件路径;未设置时断言抛出StateError。
pickImage():maxWidth / maxHeight / imageQuality 不支持
The arguments
maxWidth,maxHeight, andimageQualityare not currently supported.
对应实现位于getImageFromSource/getImage/getMultiImage。源码注释说明这些参数即使被传入也会被静默忽略(silently ignored),不会报错,但也不会有任何缩放或压缩效果:
// [ImagePickerOptions] options are not currently supported. If any // of its fields are set, they will be silently ignored.也就是说,在 Linux 上对图片做尺寸裁剪、质量压缩的期望应放到选完文件之后自行处理(例如使用package:image进行后处理)。
pickVideo():maxDuration 不支持
The argument
maxDurationis not currently supported.
对应getVideo实现,maxDuration与preferredCameraDevice同样被静默忽略:
// `preferredCameraDevice` and `maxDuration` arguments are not currently // supported. If either of these arguments are supplied, they will be silently // ignored.内部实现:如何用 file_selector 完成媒体选择
ImagePickerLinux对ImageSource.gallery的处理非常直接——构造一个带 MIME 类型过滤的XTypeGroup,然后调用file_selector平台接口弹出系统文件选择对话框:
- 选图片(getImageFromSource):
XTypeGroup(label: 'Images', mimeTypes: ['image/*']),调用fileSelector.openFile(...); - 选视频(getVideo):
XTypeGroup(label: 'Videos', mimeTypes: ['video/*']),同样调用openFile(...); - 多选图片(getMultiImage):改为调用
fileSelector.openFiles(...); - 多选视频(getMultiVideoWithOptions):
openFiles(...),类型过滤为video/*; - 图片/视频混合选择(getMedia):
XTypeGroup(label: 'Images and videos', mimeTypes: ['image/*', 'video/*']),并根据options.allowMultiple决定调用openFiles还是openFile。
测试文件 image_picker_linux_test.dart 使用 Mockito 对FileSelectorPlatform打桩,逐一验证了pickImage、getImage、getImageFromSource、getMultiImage、pickVideo、getVideo、getMultiVideoWithOptions、getMedia传出的XTypeGroup.mimeTypes是否精确匹配(图片为['image/*']、视频为['video/*']、混合为['image/*', 'video/*']),并验证了单/多选时空结果(用户取消对话框)能被优雅处理,不会抛出异常。
通过 cameraDelegate 启用相机能力
虽然 README 将ImageSource.camera列为限制,但它也给出了明确的解除路径:设置cameraDelegate。机制定义在平台接口包的 camera_delegate.dart 中,ImagePickerCameraDelegate抽象类要求实现takePhoto与takeVideo两个方法,每个方法都接收带preferredCameraDevice的ImagePickerCameraDelegateOptions。
image_picker主 README 给出了标准接入姿势(建议在main()中尽早设置):
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; class MyCameraDelegate extends ImagePickerCameraDelegate { @override Future<XFile?> takePhoto({ ImagePickerCameraDelegateOptions options = const ImagePickerCameraDelegateOptions(), }) async { return _takeAPhoto(options.preferredCameraDevice); } @override Future<XFile?> takeVideo({ ImagePickerCameraDelegateOptions options = const ImagePickerCameraDelegateOptions(), }) async { return _takeAVideo(options.preferredCameraDevice); } } void setUpCameraDelegate() { final ImagePickerPlatform instance = ImagePickerPlatform.instance; if (instance is CameraDelegatingImagePickerPlatform) { instance.cameraDelegate = MyCameraDelegate(); } }设置之后,ImagePickerLinux收到ImageSource.camera的请求会直接委托给你的MyCameraDelegate,pickImage(source: ImageSource.camera)等调用即可正常工作。社区也可以基于ImagePickerCameraDelegate构建独立的桌面相机 UI 包,供各桌面平台复用。由于 Linux 实现中没有现成的拍照实现,这部分 UI 与拍摄逻辑需要由使用方自行提供。
在 Linux 上运行示例
仓库为这个实现包附带了一个完整的示例应用(example/lib/main.dart),它直接使用ImagePickerPlatform.instance的底层 API(getVideo、getMultiVideoWithOptions、getMedia、getImageFromSource、getMultiImageWithOptions),覆盖了单选/多选图片、单选/多选视频、混合媒体选择以及通过video_player内嵌播放所选视频等场景。示例的 pubspec.yaml 通过path: ..引用本地插件源码,便于在开发本包时直接联调。
需要注意:该示例是面向插件开发者的平台实现测试应用(详见其 README),目的是做手动与自动化集成测试;实际业务应用应使用面向用户的image_picker包,而非直接依赖本实现包。
小结
image_picker_linux是联邦插件架构在 Linux 桌面的一个简洁范例:通过 endorsed 机制零配置接入,内部以file_selector系统对话框为唯一选择通道,用XTypeGroup的 MIME 过滤实现图片/视频/混合媒体的单选与多选。接入前只需记住三条边界:相机需要cameraDelegate、图片尺寸与质量参数被忽略、视频时长参数被忽略。对于绝大多数"从本机选一张图/一段视频"的桌面需求,它已经足够直接可用。
【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考