奇淫巧技-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#呢,答案是可行的,請看以下分解。java

環境

爲了可以使用Flutter調用C#,須要以下工具和環境android

前面四項不在贅述,請參考官方文檔,確保Flutter,Xamarin能夠運行項目,Android ndk請使用r15c版本,目前好像僅支持r15c,其餘未測試。ios

Embeddinator-4000是將C#轉化爲各平臺本機代碼的工具,可使用Nuget安裝git

Install-Package Embeddinator-4000 -Version 0.4.0github

將工具路徑添加到系統環境PATH,建議添加nuget的全局緩存,相似C:\Users\Administrator\.nuget\packages\embeddinator-4000\0.4.0\toolswindows

若是工具使用出錯,請檢查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/707async

使用方法

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添加進依賴。

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

結語

不少時候咱們應該摒棄語言之爭,語言並沒有好壞,甚至能夠將其融合。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息