本文主要介绍Flutter Plugin原理以及其开发和发布过程。html
Flutter优点主要体如今UI上--高性能且跨平台表现一致。可是针对平台(Android、IOS)的实现,如:获取电量、判断WiFi使用、调起WebView加载网页等,得调用特定平台的API包。Flutter Plugin就是为调用平台API而生。前端
下文中所说起到的"平台"指的是Android、IOS两端。android
包含针对Android(Java或Kotlin代码)或iOS(Objective-C或Swift代码)的原生实现,经过Platform Channels
与FLutter(dart)层通信并暴露API。ios
name
做为区分。线程安全
,故平台跟Flutter Engine的全部交互必须在平台的主线程
中执行的。接下来介绍使用Android Studio建立Flutter Plugin。使用Visual Studio Code建立的过程也是大同小异,机智的你必定能触类旁通,在这里就不一一细说。swift
工程建立完成后的目录结构以下:api
注:从 Flutter 1.9 开始,iOS 新项目默认使用 Swift 语言,而非 Objective-C;Android 新项目则默认使用 Kotlin,而非 Java。若有须要,是可随时切换回以前的 Objective-C 或 Java。 安全
咱们先看看示例工程在Android模拟器上的运行效果:异步
进入example工程目录,运行lib/main.dart。async
APP在Android模拟器运行后,能够看到屏幕出现了"Running on: Android 9"。ide
接下来咱们经过代码看看flutter是怎么显示出当前平台的系统版本。
关键代码:
...
import 'package:flutter_plugin_eg/flutter_plugin_eg.dart';
...
platformVersion = await FlutterPluginEg.platformVersion;
...
setState(() {
_platformVersion = platformVersion;
});
...
body: Center(
child: Text('Running on: $_platformVersion\n'),
)
复制代码
示例工程中的lib/main.dart引入了咱们刚刚建立Flutter Plugin中dart API实现flutter_plugin_eg.dart
。
随后使用异步的方式调用flutter_plugin_eg.dart
的FlutterPluginEg.platformVersion
并把返回值赋值给platformVersion
,随后经过setState
方法把platformVersion
的值赋值给当前状态组件的_platformVersion
,触发UI重渲把_platformVersion
的值"Android 9"显示出来。
全量代码:
import 'dart:async';
import 'package:flutter/services.dart';
class FlutterPluginEg {
static const MethodChannel _channel =
const MethodChannel('flutter_plugin_eg');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
}
复制代码
service.dart
暴露与平台通信的API,如:MethodChannel
Platform Channel的一种类型_channel
是FlutterPluginEg类的属性,是一个实例化的MethodChannel
,name
为"flutter_plugin_eg"platformVersion
是FlutterPluginEg类的静态可计算属性
,会异步返还一个String。platformVersion
中,调用_channel
的invokeMethod
方法,入参"getPlatformVersion"为调用平台约定的方法名。而后把invokeMethod
的异步结果赋值给String version
做为platformVersion
的返回值。android/src/main/kotlin/.../FlutterPluginEgPlugin.kt 全量代码:
package com.yy.flutter_plugin_eg
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
class FlutterPluginEgPlugin: MethodCallHandler {
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "flutter_plugin_eg")
channel.setMethodCallHandler(FlutterPluginEgPlugin())
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
}
复制代码
再次强调:一个Flutter应用是能够有多个
channel
,并而每一个channel
均可以有多个method
,因此须要重点了解平台的代码是经过怎么样去对接channel name 与method name。从上文.kt源码能够看到:
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "flutter_plugin_eg")
channel.setMethodCallHandler(FlutterPluginEgPlugin())
}
}
复制代码
Android ${android.os.Build.VERSION.RELEASE}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
复制代码
当channel name 和 method name 约定后,Flutter Plugin就能够在dart中方便调用平台的实现,并暴露API供Flutter项目使用。
ios/Classes/SwiftFlutterPluginEgPlugin.swift
import Flutter
import UIKit
public class SwiftFlutterPluginEgPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_plugin_eg", binaryMessenger: registrar.messenger())
let instance = SwiftFlutterPluginEgPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
result("iOS " + UIDevice.current.systemVersion)
}
}
复制代码
能够看出,IOS与Android实现思路雷同:经过"flutter_plugin_eg"注册FlutterMethodChannel
并开始监听。
但惊奇发现Flutter Plugin中swift默认生成的代码竟然没FlutterMethodCall方法名判断,在swift断点看是能获取到"getPlatformVersion"这个方法名的。
![]()
IOS模拟器上运行效果:
轮子造好后,能够发布到pub.dev,如下内容纯属搬砖。
在Flutter Plugin根目录添加
一旦你实现了一个包,你能够在Pub上发布它 ,这样其余开发人员就能够轻松使用它
在发布以前,检查pubspec.yaml、README.md以及CHANGELOG.md文件,以确保其内容的完整性和正确性。
而后, 运行 dry-run 命令以查看是否都准备OK了:
flutter packages pub publish --dry-run
复制代码
最后, 运行发布命令:
flutter packages pub publish
复制代码
有关发布的详细信息,请参阅Pub publishing docs
开发一个功能完备的APP,说到底仍是须要有原平生台开发的能力,就如Flutter Plugin须要开发原平生台部分。相信有不少Web前端童鞋也开始接触Flutter,可是若是不去深刻了解原生开发,那么也只能停留在UI层上。