Package 与 Plugin 开发:纯 Dart 包与平台插件
mediumflutterpackagepluginpubffidart-nativefederated-pluginendorsement
Package vs Plugin
Package(纯 Dart 包)
├── 只含 Dart/Flutter 代码
├── 不依赖平台 API
└── 示例:collection、freezed、dartz
Plugin(平台插件)
├── Dart API(公共接口)
├── Android 实现(Kotlin/Java)
├── iOS 实现(Swift/ObjC)
└── 示例:camera、url_launcher、flutter_secure_storage
创建 Package
# 纯 Dart package
flutter create --template=package my_utils
# Plugin(包含平台代码)
flutter create --template=plugin --platforms=android,ios my_sensor_plugin
# Dart-only plugin(基于 FFI,用 dart:ffi 调用原生)
flutter create --template=plugin_ffi my_native_lib
目录结构(Plugin)
my_sensor_plugin/
├── lib/
│ └── my_sensor_plugin.dart # Dart 公共 API
├── android/
│ └── src/main/kotlin/
│ └── SensorPlugin.kt # Android 实现
├── ios/
│ └── Classes/
│ └── SensorPlugin.swift # iOS 实现
├── example/ # 示例 app
└── pubspec.yaml
Federated Plugin —— 联邦插件
大型插件(如 url_launcher)使用联邦架构,将实现拆分为独立包:
url_launcher/ ← 应用层引用(仅依赖 app 包)
url_launcher_android/ ← Android 实现
url_launcher_ios/ ← iOS 实现
url_launcher_web/ ← Web 实现
url_launcher_platform_interface/ ← 抽象接口(Plugin Interface)
优点:
- 各平台独立发布,版本互不影响
- 社区可贡献新平台(如 Window/Linux 支持)
- 只有用到的平台实现才会被编译
// platform_interface 包(接口定义)
abstract class UrlLauncherPlatform extends PlatformInterface {
UrlLauncherPlatform() : super(token: _token);
static final Object _token = Object();
static UrlLauncherPlatform _instance = MethodChannelUrlLauncher();
static UrlLauncherPlatform get instance => _instance;
static set instance(UrlLauncherPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<bool> launch(String url) => throw UnimplementedError();
}
pubspec.yaml 关键配置
name: my_sensor_plugin
description: A Flutter plugin for sensor data.
version: 0.1.0
homepage: https://github.com/example/my_sensor_plugin
environment:
sdk: '>=3.0.0 <4.0.0'
flutter: '>=3.10.0'
dependencies:
flutter:
sdk: flutter
flutter:
plugin:
platforms:
android:
package: com.example.my_sensor_plugin
pluginClass: MySensorPlugin
ios:
pluginClass: MySensorPlugin
FFI Plugin —— 直接调用 C/C++ 库
当需要复用现有 C/C++ 库(算法、加密、音视频处理)时,FFI plugin 比 MethodChannel 性能更好(无序列化开销):
// lib/src/my_native_lib.dart
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
// 加载动态库
final DynamicLibrary _lib = Platform.isAndroid
? DynamicLibrary.open('libmynativelib.so')
: DynamicLibrary.process();
// Native 函数签名
typedef _CAdd = Int32 Function(Int32 a, Int32 b);
typedef _DartAdd = int Function(int a, int b);
// 绑定
final _add = _lib.lookupFunction<_CAdd, _DartAdd>('native_add');
// 公共 API
int add(int a, int b) => _add(a, b);
// src/mynativelib.c
#include <stdint.h>
// FFI_PLUGIN_EXPORT 宏确保符号导出
FFI_PLUGIN_EXPORT intptr_t native_add(intptr_t a, intptr_t b) {
return a + b;
}
发布到 pub.dev
# 检查发布准备情况
dart pub publish --dry-run
# 发布(需要 Google 账号登录)
dart pub publish
pub.dev 评分(影响搜索排名):
- Likes:用户点赞数
- Pub Points:平台检查分(文档完整、changelog、analysis_options 配置、平台支持)
- Popularity:30天内被引用的包数量
获得高分的关键:
- 完整的 README(示例代码/GIF)
- example app
- 所有公共 API 有 dartdoc 注释
- 支持多平台
- 无
dart analyze警告
核心考点
Q:package 和 plugin 的区别?
package 是纯 Dart 代码,不含平台相关代码;plugin 是 package 的超集,额外包含 Android/iOS native 代码,通过 MethodChannel 或 FFI 与 Dart 层通信。
Q:什么是联邦插件(Federated Plugin)?
将一个插件拆分为多个独立 pub 包:app 包(用户引用)、platform_interface 包(接口抽象)、各平台实现包。好处是各平台实现可以独立迭代,支持社区贡献新平台,且只打包用到的平台代码。