2、创建第一个Flutter插件项目
好,咱们直接动手。这一章我会带你从零创建一个Flutter插件项目,然后把它跑起来。你想想看,一个插件项目到底长什么样?里面那些android、ios、lib目录都是干嘛的?咱们今天一次性说清楚。
2.1 使用flutter create创建插件项目
创建Flutter插件,官方推荐用这条命令:
flutter create --template=plugin --org com.example my_first_plugin
这里解释一下参数:
--template=plugin:告诉Flutter你要创建的是插件项目,不是普通应用--org com.example:指定包名,我习惯用公司域名倒写,比如com.mycompanymy_first_plugin:项目名称,建议全小写加下划线
执行完之后,你会看到终端输出一堆信息。嗯,这里要注意——如果你用的是Flutter 3.x以上版本,它还会问你要不要支持某些平台。我个人建议先全选,后面再删减都来得及。
--platforms=android,ios。我在早期项目里经常这么干,省得生成一堆用不上的目录。
2.2 项目结构解析
创建完成后,用VS Code或Android Studio打开项目。你会看到这样的目录结构:
my_first_plugin/
├── android/ # Android原生代码
├── ios/ # iOS原生代码
├── lib/ # Dart代码(插件API定义)
├── example/ # 示例应用
├── test/ # 单元测试
├── pubspec.yaml # 插件配置文件
└── CHANGELOG.md # 版本更新日志
咱们一个一个说。
2.2.1 android/ 目录
这里面放的是Android原生代码。说白了,就是Java或Kotlin写的代码。Flutter通过MethodChannel跟它通信。我刚开始做插件时,经常在Android Studio里单独打开这个目录来调试,因为Android原生代码的断点只能在AS里生效。
关键文件:
android/src/main/java/.../MyFirstPlugin.java:插件的主入口类android/build.gradle:Android构建配置,可以在这里加依赖库android/src/main/AndroidManifest.xml:权限声明
2.2.2 ios/ 目录
iOS原生代码放在这里。用Swift或Objective-C写。我记得第一次写iOS插件时,被Xcode的配置折腾了半天——桥接头文件、Podfile、Swift版本……嗯,这些坑后面会专门讲。
关键文件:
ios/Classes/MyFirstPlugin.swift:插件的主入口类ios/my_first_plugin.podspec:CocoaPods配置文件
2.2.3 lib/ 目录
这是Dart代码的根据地。插件对外暴露的API都写在这里。比如:
// lib/my_first_plugin.dart
import 'dart:async';
import 'package:flutter/services.dart';
class MyFirstPlugin {
static const MethodChannel _channel = MethodChannel('my_first_plugin');
static Future<String?> getPlatformVersion() async {
final version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
}
你看,这里定义了一个MethodChannel,名字叫my_first_plugin。这个字符串必须跟Android和iOS端注册的channel名字一致,否则通信会失败。我曾经因为拼写错误,排查了整整一个下午……
2.2.4 example/ 目录
这是一个完整的Flutter应用,专门用来测试你的插件。它有自己的pubspec.yaml,并且通过path依赖引用父目录的插件:
dependencies:
my_first_plugin:
path: ../
这样做的好处是:你改完插件代码,不用发布到pub.dev,直接在example里就能看到效果。我平时开发插件,90%的时间都在example里调试。
2.3 运行示例应用
好,现在咱们把示例应用跑起来。打开终端,进入example目录:
cd my_first_plugin/example
flutter run
如果你连接了真机或模拟器,Flutter会自动安装并启动应用。你会看到一个简单的界面,显示当前设备的平台版本——比如"Android 13"或"iOS 16.4"。
getPlatformVersion()方法。这个方法通过MethodChannel发送消息到原生端,原生端获取系统版本后返回给Dart层。整个过程就是一次标准的Flutter与原生交互。
2.4 知识体系结构图
下面这张图帮你理清整个插件项目的核心逻辑:
这张图展示了插件工作的三层结构:Flutter层通过MethodChannel调用原生层,原生层再调用系统API。example应用则位于最上层,用来验证整个链路是否通畅。
2.5 避坑指南
- Channel名字不一致:Dart端和原生端的channel名字必须完全一样,大小写敏感。我建议把channel名字定义成常量,两边共用。
- Android包名冲突:如果你同时开发多个插件,注意
--org参数要不同,否则Android编译时会报Duplicate class错误。 - iOS模拟器问题:有些iOS功能(比如相机、蓝牙)在模拟器上不支持,跑不起来别慌,换真机试试。
2.6 小结
这一章我们完成了三件事:创建了第一个Flutter插件项目、搞清楚了每个目录的作用、成功运行了示例应用。说白了,你现在已经知道插件项目长什么样了。下一章我们会深入MethodChannel的通信细节,看看Dart和原生代码到底是怎么「打电话」的。
公众号:蓝海资料掘金营,微信deep3321