本文主要介紹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層上。