Kotlin/Native 用KMM写Flutter插件
一、用KMM写Flutter插件
Google官方有一个写Flutter例子How to write a Flutter plugin,这里把Google plugin_codelab 例子改成用KMM写Flutter插件。
二、如何运行
Github项目地址:kmm-flutter-plugin
Android: run shared/plugin_codelab/example/android
iOS:
1、build shared.framework
use ./gradlew releaseIOSFramework
or use new version Android Studio sync
2、run shared/plugin_codelab/example/ios
Tips: before run,shared/build/cocoapods/framework/shared.framework should be generated. The shared.h header file shared/build/cocoapods/framework/shared.framework/Headers/shared.h is generated.
三、设计思路
Android/iOS插件PluginCodelabPlugin只需要实现KMM Module的接口,不写任何逻辑,把逻辑通过接口放在KMM Module中。
1、定义接口中间层用于转发数据
如参考Flutter插件的MethodCall、MethodChannel,定义CommonMethodCall数据类、CommonMethodChannel.Result接口。
data class CommonMethodCall(
val method: String,
val arguments: Any?,
)
class CommonMethodChannel {
interface Result {
fun success(result: Any?)
fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?)
fun notImplemented()
}
}
2、在KMM中的commonMain实现CommonCodelabPlugin插件的公共逻辑
CommonCodelabPlugin需要初始化并启动synth?.start(),处理getPlatformVersion、onKeyDown、onKeyUp逻辑。
class CommonCodelabPlugin {
private val synth = Synth()
init {
synth?.start()
}
fun onMethodCall(call: CommonMethodCall, result: CommonMethodChannel.Result) {
when (call.method) {
"getPlatformVersion" -> {
result.success(Platform().platform)
}
"onKeyDown" -> {
try {
val arguments = call.arguments as List<*>
val numKeysDown = synth?.keyDown((arguments[0] as Int))
result.success(numKeysDown)
} catch (ex: Exception) {
result.error("1", ex.message, ex.cause)
}
}
"onKeyUp" -> {
try {
val arguments = call.arguments as List<*>
val numKeysDown = synth?.keyUp((arguments[0] as Int))
result.success(numKeysDown)
} catch (ex: Exception) {
result.error("1", ex.message, ex.cause)
}
}
else -> {
result.notImplemented()
}
}
}
}
还有包括插件名称也属于公共逻辑
// 插件Channel名称
const val PLUGIN_CODE_LAB_CHANNEL = "plugin_codelab"
3、实现平台差异特性
这里只列出expect接口,具体实现平台差异特性类请查看源码
expect class Synth() {
fun start()
fun keyDown(key: Int): Int
fun keyUp(key: Int): Int
}
expect class Platform() {
val platform: String
}
4、Android Flutter实现插件KMM接口
Android Flutter实现插件KMM接口,注意这里只实现接口用于中转Flutter与Android/iOS 数据,不能有任何业务逻辑
class PluginCodelabPlugin : FlutterPlugin, MethodCallHandler {
private var channel: MethodChannel? = null
private var commonCodelabPlugin: CommonCodelabPlugin? = null
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
setup(this, flutterPluginBinding.binaryMessenger)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
commonCodelabPlugin?.onMethodCall(
call = CommonMethodCall(call.method, call.arguments),
result = object : CommonMethodChannel.Result {
override fun success(successResult: Any?) {
result.success(successResult)
}
override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
result.error(errorCode, errorMessage, errorDetails)
}
override fun notImplemented() {
result.notImplemented()
}
})
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel?.setMethodCallHandler(null)
}
companion object {
private fun setup(plugin: PluginCodelabPlugin, binaryMessenger: BinaryMessenger) {
plugin.channel = MethodChannel(binaryMessenger, PLUGIN_CODE_LAB_CHANNEL)
plugin.channel?.setMethodCallHandler(plugin)
plugin.commonCodelabPlugin = CommonCodelabPlugin()
}
}
}
5、iOS Flutter实现插件KMM接口
Android Flutter实现插件KMM接口,注意这里只实现接口用于中转Flutter与Android/iOS 数据,不能有任何业务逻辑
#import "PluginCodelabPlugin.h"
@implementation PluginCodelabPlugin{
int _numKeysDown;
FlutterResult _flutterResult;
SharedCommonCodelabPlugin* _codelabPlugin;
}
- (instancetype)init {
self = [super init];
if (self) {
// create music
_codelabPlugin = [[SharedCommonCodelabPlugin alloc] init];
}
return self;
}
- (void)dealloc {
// destroy music
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName: SharedPluginCodeLabKt.PLUGIN_CODE_LAB_CHANNEL
binaryMessenger:[registrar messenger]];
PluginCodelabPlugin* instance = [[PluginCodelabPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall *)call
result:(FlutterResult)result {
SharedCommonMethodCall *methodCall = [[SharedCommonMethodCall alloc] initWithMethod:call.method arguments:call.arguments];
_flutterResult = result;
[_codelabPlugin onMethodCallCall:methodCall result:self ];
}
- (void)errorErrorCode:(NSString * _Nullable)errorCode errorMessage:(NSString * _Nullable)errorMessage errorDetails:(id _Nullable)errorDetails {
NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:errorCode.intValue userInfo:@{@"errorMessage":errorMessage, @"errorDetails":errorDetails}];
if (_flutterResult) {
_flutterResult(error);
}
}
- (void)notImplemented {
if (_flutterResult) {
_flutterResult(FlutterMethodNotImplemented);
}
}
- (void)successResult:(id _Nullable)result {
if (_flutterResult) {
_flutterResult(result);
}
}
@end
到这里,已经完成了使用KMM开发一个Flutter插件。使用KMM开发插件的好处是公共逻辑都使用kotlin写,一般公共逻辑比较简单适合使用kotlin写,便于维护。而且,实现了KMM写插件,Flutter写UI。
四、参考链接
本文地址:https://www.cnblogs.com/liqw/p/15477079.html
Github项目地址:kmm-flutter-plugin
Kotlin/Native 用KMM写Flutter插件的更多相关文章
- Kotlin/Native KMM项目架构
一.什么是KMM? Kotlin Multiplatform Mobile ( KMM ) 是一个 SDK,旨在简化跨平台移动应用程序的创建.在 KMM 的帮助下,您可以在 iOS 和 Android ...
- 移动端跨平台方案对比:React Native、weex、Flutter
跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架百花齐放,颇有一股推倒原生开发者的势头. 为什么我们需 ...
- 最火移动端跨平台方案盘点:React Native、weex、Flutter
1.前言 跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架的百花齐放,颇有一股推倒原生开发者的势头. ...
- Flutter实战:手把手教你写Flutter Plugin
前言 如果你对移动端有所关注,那么你一定会听说过Flutter.得益于Google,Flutter一经推出便得受到了广泛关注.很多开发者跃跃欲试,国内部分大厂,诸如美团.闲鱼等团队已经开始了Flutt ...
- Flutter学习(9)——Flutter插件实现(Flutter调用Android原生
原文地址: Flutter学习(9)--Flutter插件实现(Flutter调用Android原生) | Stars-One的杂货小窝 最近需要给一个Flutter项目加个apk完整性检测,需要去拿 ...
- 自己写jquery插件之模版插件高级篇(一)
需求场景 最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到.这里不讨论它的用户体验怎么样. 仅仅是从复用的角度,如果每个页面都去写text和select元素,两个b ...
- 锋利的jQuery--编写jQuery插件(读书笔记五)[完结篇]
1.表单验证插件Validation 2.表单插件Form 3.动态事件绑定插件livequery 可以为后来的元素绑定事件 类似于jQuery中的live()方法 4.jQuer ...
- 什么?你还不会写JQuery 插件
前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论 ...
- 写JQuery 插件 什么?你还不会写JQuery 插件
http://www.cnblogs.com/Leo_wl/p/3409083.html 前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui ...
随机推荐
- uniapp 获取用户手机号
参考资料: 微信小程序官方文档 uniapp开发微信小程序获取用户手机号 页面增加一个按钮 <button open-type="getPhoneNumber" @getph ...
- LinkedList 添加元素源码解析
jdk版本:1.8 LinkedList添加元素有两个方法:add(E e)和add(int index,E e). add(E e) /** * Appends the specified elem ...
- Fastjson 1.2.22-24 反序列化漏洞分析(2)
Fastjson 1.2.22-24 反序列化漏洞分析(2) 1.环境搭建 我们以ubuntu作为被攻击的服务器,本机电脑作为攻击者 本机地址:192.168.202.1 ubuntu地址:192.1 ...
- 日期SQL 脚本
一个月第一天的 SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)本周的星期一 SELECT DATEADD(wk, DATEDIFF(wk,0,g ...
- PHP中使用if的时候为什么建议将常量放在前面?
在某些框架或者高手写的代码中,我们会发现有不少人喜欢在进行条件判断的时候将常量写在前面,比如: if(1 == $a){ echo 111; } 这样做有什么好处呢?我们假设一个不小心的粗心大意,少写 ...
- Jmeter扩展组件开发(10) - 自定义扩展函数助手的开发
CODE package com.functions;import org.apache.jmeter.engine.util.CompoundVariable;import org.apache.j ...
- yapi 事件创建、修改等接口事件监听
使用的yapi作为接口文档平台.出于业务需求需要对接口创建.修改.删除等事件进行监听. yapi已经实现并预留了这个口子,但是没有找到实现的文档.这里进行简单描述下使用的方式. 一.yapi创建.修改 ...
- ubuntu中如何切换普通用户、root用户
1.打开Ubuntu,输入命令:su root,回车提示输入密码,输入密码后提示:认证失败. 2.给root用户设置密码: 命令:sudo passwd root 输入密码,并确认密码. 3.重新输入 ...
- ci框架 自定义配置方法
系统自动在Application文件夹下生成的config.php文件,采用key-value关联数组的形式来存放配置项和值.为了使结构更清晰,手动新建另外一个配置文件myconfig.php,所采用 ...
- python对象引用和垃圾回收
变量="标签" 变量a和变量b引用同一个列表: >>> a = [1, 2, 3] >>> b = a >>> a.appen ...