一、用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插件的更多相关文章

  1. Kotlin/Native KMM项目架构

    一.什么是KMM? Kotlin Multiplatform Mobile ( KMM ) 是一个 SDK,旨在简化跨平台移动应用程序的创建.在 KMM 的帮助下,您可以在 iOS 和 Android ...

  2. 移动端跨平台方案对比:React Native、weex、Flutter

    跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架百花齐放,颇有一股推倒原生开发者的势头. 为什么我们需 ...

  3. 最火移动端跨平台方案盘点:React Native、weex、Flutter

    1.前言 跨平台一直是老生常谈的话题,cordova.ionic.react-native.weex.kotlin-native.flutter等跨平台框架的百花齐放,颇有一股推倒原生开发者的势头. ...

  4. Flutter实战:手把手教你写Flutter Plugin

    前言 如果你对移动端有所关注,那么你一定会听说过Flutter.得益于Google,Flutter一经推出便得受到了广泛关注.很多开发者跃跃欲试,国内部分大厂,诸如美团.闲鱼等团队已经开始了Flutt ...

  5. Flutter学习(9)——Flutter插件实现(Flutter调用Android原生

    原文地址: Flutter学习(9)--Flutter插件实现(Flutter调用Android原生) | Stars-One的杂货小窝 最近需要给一个Flutter项目加个apk完整性检测,需要去拿 ...

  6. 自己写jquery插件之模版插件高级篇(一)

    需求场景 最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到.这里不讨论它的用户体验怎么样. 仅仅是从复用的角度,如果每个页面都去写text和select元素,两个b ...

  7. 锋利的jQuery--编写jQuery插件(读书笔记五)[完结篇]

    1.表单验证插件Validation   2.表单插件Form   3.动态事件绑定插件livequery 可以为后来的元素绑定事件   类似于jQuery中的live()方法     4.jQuer ...

  8. 什么?你还不会写JQuery 插件

    前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论 ...

  9. 写JQuery 插件 什么?你还不会写JQuery 插件

    http://www.cnblogs.com/Leo_wl/p/3409083.html 前言 如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui ...

随机推荐

  1. element-ui 弹出组件的遮罩层在弹出层dialog模态框的上面

     造成的原因: 因为dialog的组件外层div设置了 position:absolute: 属性所以导致遮罩层会在最上面. 解决方法: 在属性内加上这段代码 :append-to-body=&quo ...

  2. 在excel中,应用公式到多行

    当一个单元格中输入公式后, 选中单元格 然后将鼠标放到右下角的控制手柄处,当鼠标变成"黑十字"标志 双击鼠标左键 即可

  3. lua中的随机数

    Lua 生成随机数需要用到两个函数:math.randomseed(xx), math.random([n [, m]]) 1. math.randomseed(n) 接收一个整数 n 作为随机序列种 ...

  4. Linux 文本相关命令(1)

    Linux 文本相关命令(1) 前言 最近线上环境(Windows Server)出现了一些问题,需要分析一下日志.感觉 Windows 下缺少了一些 Linux 系统中的小工具,像在这波操作中用到的 ...

  5. 【C++基础教程】第二课

    一,上次的课后练习答案 1,输出1+2=3 2,输出2 2.25 2.25 2.25 3,第一空iostream或bits/stdc++.h 第二空main(),main(void)或main(int ...

  6. JSON,XML设计模式详解

    JSON在Java中的应用: Json概念: json 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式用来存储和表示数据.JSON的语言简洁清晰,广为大众所欢迎,是一种理想的数据交换语言 ...

  7. PHP中命名空间是怎样的存在?(二)

    今天带来的依然是命名空间相关的内容,本身命名空间就是PHP中非常重要的一个特性.所以关于它的各种操作和使用还是非常复杂的,光使用方式就有很多种,我们一个一个的来看. 子命名空间 命名空间本身就像目录一 ...

  8. ecshop增加调用字段问题汇总

    一.ecshop文章列表页调用缩略图.网页描述等 打开includes/lib_article.php文件,大约在69行 添加 $arr[$article_id]['description'] = $ ...

  9. Docker DevOps实战:GitLab+Jenkins(1)- GitLab容器搭建、使用SourceTree pull/push项目

    GitLab容器搭建 # 创建GitLab容器# --restart always #重启,容器自动重启# --privileged=true #容器内使用root权限 [root@localhost ...

  10. 51nod1676-无向图同构【乱搞】

    正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId=1676 题目大意 给出两张\(n\)个点\(m\)条边的无向图,求这两张图 ...