Kotlin/Native 用KMM写Flutter插件

编程之家收集整理的这篇文章主要介绍了Kotlin/Native 用KMM写Flutter插件编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、用KMM写Flutter插件

@H_419_2@Google官方有一个Flutter例子How to write a Flutter plugin,这里把Google plugin_codelab 例子改成用KMM写Flutter插件

二、如何运行

@H_419_2@Github项目地址:kmm-flutter-plugin

@H_419_2@Android: run shared/plugin_codelab/example/android

@H_419_2@iOS:

@H_419_2@1、build shared.framework

@H_502_15@use ./gradlew releaseIOSFramework
or use new version Android Studio sync
@H_419_2@2、run shared/plugin_codelab/example/ios

@H_419_2@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.

三、设计思路

@H_419_2@Android/iOS插件PluginCodelabPlugin只需要实现KMM Module的接口,不写任何逻辑,把逻辑通过接口放在KMM Module中。

1、定义接口中间层用于转发数据

@H_419_2@如参考Flutter插件的MethodCall、MethodChannel,定义CommonMethodCall数据类、CommonMethodChannel.Result接口。

@H_502_15@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插件的公共逻辑

@H_419_2@CommonCodelabPlugin需要初始化并启动synth?.start(),处理getPlatformVersion、onKeyDown、onKeyUp逻辑。

@H_502_15@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.cause)
                }
            }
            else -> {
                result.notImplemented()
            }
        }
    }
}
@H_419_2@还有包括插件名称也属于公共逻辑

@H_502_15@// 插件Channel名称
const val PLUGIN_CODE_LAB_CHANNEL = "plugin_codelab"

3、实现平台差异特性

@H_419_2@这里只列出expect接口,具体实现平台差异特性类请查看源码

@H_502_15@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接口

@H_419_2@Android Flutter实现插件KMM接口,注意这里只实现接口用于中转Flutter与Android/iOS 数据,不能有任何业务逻辑

@H_502_15@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?,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接口

@H_419_2@Android Flutter实现插件KMM接口,注意这里只实现接口用于中转Flutter与Android/iOS 数据,不能有任何业务逻辑

@H_502_15@#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
@H_419_2@到这里,已经完成了使用KMM开发一个Flutter插件。使用KMM开发插件的好处是公共逻辑都使用kotlin写,一般公共逻辑比较简单适合使用kotlin写,便于维护。而且,实现了KMM写插件Flutter写UI。

四、参考链接

@H_419_2@本文地址:https://www.cnblogs.com/liqw/p/15477079.html
Github项目地址:kmm-flutter-plugin

总结

以上是编程之家为你收集整理的Kotlin/Native 用KMM写Flutter插件全部内容,希望文章能够帮你解决Kotlin/Native 用KMM写Flutter插件所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您喜欢寻找一群志同道合、互帮互助的学习伙伴,可以点击下方链接加入:
编程之家官方1群
编程之家官方2群
编程之家官方3群
编程之家官方4群

相关文章

猜你在找的Android相关文章

第一部分 个性化控件(View)主要介绍那些不错个性化的 View,包括 ListView、ActionBar、Menu、ViewPager、Gallery、GridView、ImageView、ProgressBar、TextView、ScrollView、TimeView、TipView、FlipView、ColorPickView、GraphView、UI Style 等等。一、Li...
View与Widget带小红点的提示:BadgeViewBadgeView(stefanjauker的,改颜色需要在BadgeView源码里面改) android-viewbadger(可以设置提示为数字或者文字,以及背景颜色)标签tagviewTAGView(可以设置背景图片的形状和颜色,可以同时显示图片和文字) android-tagview(Android-Cloud-Ta...
内容抽屉菜单 ListView WebView SwitchButton 按钮 点赞按钮 进度条 TabLayout 图标 下拉刷新 ViewPager 图表(Chart) 菜单(Menu) 浮动菜单 对话框 空白页 滑动删除 手势操作 RecyclerView Card Color Drawable Spinner 布局 模糊效果 TabBar AppBar 选择器(Picker) 跑马灯 日历时间 主题样式 ImageView 通知
Android Context作用Context 用于访问全局信息的接口App的资源: strings, drawable资源等等下面咱们来看一个例子public class MainActivity extends Activity { String TAG = "CARLOZ"; @Override protected void onCreate(Bundle savedIn
broadcast, aidl和Content Provider的区别和适用场所这3种都可以实现跨进程的通信,那么从效率,适用范围,安全性等方面来比较的话他们3者之间有什么区别?最好举个例子的。broadcast:用于发送和接收广播!实现信息的发送和接收! aidl:用于不同程序将服务的相互调用!实现了一个程序为另一个程序服务的功能! Content Provider:用于将程序的数据库人为地
net与wap什么意思WAP上网所谓WAP(Wireless Application Protocol)即无线应用协议,是一项全球性的网络通信协议。WAP使移动Internet 有了一个通行的标准,其目标是将Internet的丰富信息及先进的业务引入到移动电话等无线终端之中。WAP定义可通用的平台,把目前Internet网上HTML语言的信息转换成用WML(Wireless Markup Langu
直接上图:
在项目中加了个Jar包 运行时 没事 打包时,在用到Jar中类的地方会崩溃加入到项目中的jar包只要project.properties文件中加了这么一句:proguard.config=proguard.cfg那么proguard.cfg 混淆文件就会起作用,在打包成APK时对项目进行混淆但是当我们加入jar包时,混淆后有些方法在虚拟机中运行会找不到要对每一个加入的ja...
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注