奇淫巧技-Flutter调用C#

前言

众所周知,Xamarin应该是.net下的跨平台开发工具。2016年之前还处于收费状态,后被微软收购后开源。但似乎有个现象,开源后的Xamarin发展似乎有些停滞,而且维护Xamarin的团队又很固执不愿变通。社区多次建议UI层应该统一绘图引擎,而不是映射原生控件。Xamarin.Forms给人的感觉就是性能差,动画僵硬,效果不好实现。以至于谷歌的Flutter火爆之后,Xamarin社区很多人便转移阵地,你在百度搜索Xamarin,第一个关键词就是xamarin还有人用么。那么对于C#/.net开发者来说,唯一的问题就是界面,就有了开源项目Xamarin.Flutter,但过完年没多久,项目就Archived了,adamped说仅靠他和几个开发人员的业余时间很难搞定。但技术上确实可行,因为Skia在.net下本来就有绑定SkiaSharp,而Flutter底层便使用的Skia引擎。UIWidgets就是在Unity3D下的Flutter实现。那对于我们.net开发者有没有一种可能就是界面使用Flutter,业务逻辑采用C#呢,答案是可行的,请看如下分解。

环境

为了能够使用Flutter调用C#,需要如下工具和环境

前面四项不在赘述,请参考官方文档,确保Flutter,Xamarin可以运行项目,Android ndk请使用r15c版本,目前好像仅支持r15c,其他未测试。

Embeddinator-4000是将C#转化为各平台本机代码的工具,可以使用Nuget安装

Install-Package Embeddinator-4000 -Version 0.4.0

将工具路径添加到系统环境PATH,建议添加nuget的全局缓存,类似C:\Users\Administrator\.nuget\packages\embeddinator-4000\0.4.0\tools

如果工具使用出错,请检查sdk,或ndk版本,并确认Xamarin设置sdk,ndk路径正确。并将如下信息添加进注册表

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Novell]

[HKEY_CURRENT_USER\Software\Novell\Mono for Android]
"AndroidNdkDirectory"="C:\\Program Files (x86)\\Android\\android-sdk\\ndk-bundle"
"AndroidSdkDirectory"="C:\\Program Files (x86)\\Android\\android-sdk"
"JavaSdkDirectory"="C:\\Program Files\\Android\\jdk\\microsoft_dist_openjdk_1.8.0.25\\"`

因为目前visualstudio的注册表信息都是对立文件形式,这可能是工具本身的BUG,参加https://github.com/mono/Embeddinator-4000/issues/707

使用方法

1. 创建C#类库(这里只实现Android 下的方法,iOS类推)

这里我们先创建一个类库,我们使用Android Class Lib,如果不是Android 的方法,也可以创建普通的类库

编译后得到Test4Flutter.dll, 运行如下命令

Embeddinator-4000.exe --gen=java -out=test .\Test4Flutter.dll -p=Android -c

出现MSBUILD : error MSB1008: 只能指定一个项目。请确保路径下没有空格,或者复制dll到其他路径重试

在test目录下我们得到一个Test4Flutter.aar文件

2.创建一个Flutter插件

Android 里添加Module,具体参考文档,将Module添加进依赖。

![dump_2046261408567477536](C:\Users\Administrator\Desktop\dump_2046261408567477536.png)  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    }
    else if (call.method.equals("getHelloString")){
      result.success(test.getHelloString());
    }
    else if(call.method.equals("add")){
      result.success(test.add((int)call.argument("x"),(int)call.argument("y")));
    }
    else {
      result.notImplemented();
    }
  }

  static Future<String> getHelloString() async {
    return await _channel.invokeMethod('getHelloString');
  }

  static Future<int> add(int x,int y) async{
    final int ret = await _channel.invokeMethod('add',<String, dynamic>{
      'x': x,
      'y': y,
    });
    return ret;
  }

example内调用测试

调用方法时控制台会打印如下

I/mono-stdout( 5946): call net function ->GetHelloString
I/mono-stdout( 5946): call net function ->Add
I/mono-stdout( 5946): call net function ->Add

很多时候我们应该摒弃语言之争,语言并无好坏,甚至可以将其融合

猜你喜欢

转载自www.cnblogs.com/LHCCC/p/11374204.html