一、Flutter 本质上只是一个 UI 框架,运行在宿主平台之上,Flutter 本身是无法提供一些系统能力,比如使用蓝牙、相机、GPS等,因此要在 Flutter 中调用这些能力就必须和原生平台进行通信。目前Flutter 已经支持 iOS、Android、Web、macOS、Windows、Linux等众多平台,要调用特定平台 API 就需要写插件。插件是一种特殊的包,和纯 dart 包主要区别是插件中除了dart代码,还包括特定平台的代码,比如 image_picker 插件可以在 iOS 和 Android 设备上访问相册和摄像头。
1. 插件实现原理
一个完整的Flutter应用程序实际上包括原生代码和Flutter代码两部分。Flutter 中提供了平台通道(platform channel)用于Flutter和原生平台的通信,平台通道正是Flutter和原生之间通信的桥梁,它也是Flutter插件的底层基础设施。
Flutter与原生之间的通信本质上是一个远程调用(RPC),通过消息传递实现:
- 应用的Flutter部分通过平台通道(platform channel)将调用消息发送到宿主应用。
- 宿主监听平台通道,并接收该消息。然后它会调用该平台的API,并将响应发送回Flutter。
由于插件编写涉及具体平台的开发知识,比如 image_picker 插件需要开发者在 iOS 和 Android 平台上分别实现图片选取和拍摄的功能
2. 获取平台信息
在 Flutter 中想根据宿主平台添加一些差异化的功能,因此 Flutter 中提供了一个全局变量 defaultTargetPlatform
来获取当前应用的平台信息,defaultTargetPlatform
定义在"platform.dart"中,它的类型是TargetPlatform
,这是一个枚举类,定义如下:
enum TargetPlatform {
android,
fuchsia,
iOS,
...
}
可以看到目前Flutter只支持这三个平台。可以通过如下代码判断平台:
if(defaultTargetPlatform == TargetPlatform.android){
// 是安卓系统,do something
...
}
...
由于不同平台有它们各自的交互规范,Flutter Material库中的一些组件都针对相应的平台做了一些适配,比如路由组件MaterialPageRoute
,它在android和ios中会应用各自平台规范的切换动画。那如果想让APP在所有平台都表现一致,比如希望在所有平台路由切换动画都按照ios平台一致的左右滑动切换风格该怎么做?Flutter中提供了一种覆盖默认平台的机制,可以通过显式指定debugDefaultTargetPlatformOverride
全局变量的值来指定应用平台。比如:
debugDefaultTargetPlatformOverride=TargetPlatform.iOS;
print(defaultTargetPlatform); // 会输出TargetPlatform.iOS
上面代码即使在Android中运行后,Flutter APP也会认为是当前系统是iOS,Material组件库中所有组件交互方式都会和iOS平台对齐,defaultTargetPlatform
的值也会变为TargetPlatform.iOS
。