鴻蒙Flutter實戰(zhàn):06-使用ArkTs開發(fā)Flutter鴻蒙插件

使用 ArkTs 開發(fā) Flutter 鴻蒙平臺插件

本文講述如何開發(fā)一個 Flutter 鴻蒙插件枫笛,如何實現(xiàn) Flutter 與鴻蒙的混合開發(fā),以及雙端消息通信多律。

Flutter側(cè)痴突,編寫 MethodChannel

const MethodChannel _methodChannel = MethodChannel('xxx.com/app');


  /// 獲取token
  static Future<dynamic> getToken() {
    return _methodChannel.invokeMethod("getPrefs", 'token');
  }

  /// 設(shè)置token
  static Future<dynamic> setToken(String token) {
    return _methodChannel
        .invokeMethod("setPrefs", {'key': 'token', 'value': token});
  }

代碼生命了一個 methodChannel, 并實現(xiàn)了 token 存錯的調(diào)用方法。

ArkTs側(cè)狼荞,實現(xiàn)調(diào)用

編寫 src/main/ets/entryability/EntryAbility.ets


import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import ForestPlugin from './ForestPlugin';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';

let dataPreferences: preferences.Preferences | null = null;

export default class EntryAbility extends FlutterAbility {

  onWindowStageCreate(windowStage: window.WindowStage): void {
    super.onWindowStageCreate(windowStage);
    preferences.getPreferences(this.context, 'forestStore', (err: BusinessError, val: preferences.Preferences) => {
      if (err) {
        console.error("Failed to get preferences. code =" + err.code + ", message =" + err.message);
        return;
      }
      dataPreferences = val;
      console.info("Succeeded in getting preferences1.");
    })
  }

  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)
    this.addPlugin(new ForestPlugin());
  }
}

export {dataPreferences};

該文件使的原生頁面在加載時辽装,配置 Flutter 引擎,注冊插件相味。 Flutter初始化時拾积,同時初始化了 首選項dataPreferences,以備后用攻走。

編寫 src/main/ets/entryability/ForestPlugin.ets

import { Any, BasicMessageChannel, EventChannel, FlutterManager, FlutterPlugin, Log, MethodCall, MethodChannel, StandardMessageCodec} from '@ohos/flutter_ohos';
import { FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
import { batteryInfo } from '@kit.BasicServicesKit';
import { MethodCallHandler, MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import {dataPreferences} from './EntryAbility';
import router from '@ohos.router'
import { webviewRouterParams } from '../pages/Webview';

const TAG = "[flutter][plugin][forest]";

export default class ForestPlugin implements FlutterPlugin {
  private channel?: MethodChannel;
  private basicChannel?: BasicMessageChannel<Any>;
  private api = new ForestApi();
  private dataPreferences: preferences.Preferences | null = null;

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(binding.getBinaryMessenger(), "xxx.com/app");
    this.channel.setMethodCallHandler({
      onMethodCall : (call: MethodCall, result: MethodResult) => {
        console.log(`${TAG}-->[${call.method}]: ${JSON.stringify(call.args)}`);
        switch (call.method) {
          case "getPrefs":
            this.api.getPrefs(String(call.args), result);
            break;
          case "setPrefs":
            let key = String(call.argument("key"));
            let value = String(call.argument("value"));
            this.api.setPrefs(key, value);
          default:
            result.notImplemented();
            break;
        }
      }
    })
  }
  //···
  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    Log.i(TAG, "onDetachedFromEngine");
    this.channel?.setMethodCallHandler(null);
  }

  getUniqueClassName(): string {
    return "ForestPlugin";
  }

以上代碼實現(xiàn)了一個插件類,其核心實現(xiàn)了FlutterPlugin中的 onAttachedToEngine方法此再,該方法在 Flutter 引擎加載成功后調(diào)用昔搂。

onMethodCall中接收來自 Flutter 的消息調(diào)用,分別實現(xiàn)了 'getPrefs' 和 'setPrefs' 兩個回掉输拇,其中 getPrefs有返回值摘符,通過 result.success(val);(見下)異步返回,
setPrefs沒有返回值策吠。

以下為 ForestApi的具體實現(xiàn)逛裤,使用了 HarmonyOS 中的首選項 API 設(shè)置和讀取數(shù)據(jù)。

class ForestApi {
  getPrefs(key: string, result: MethodResult) {
    dataPreferences?.get(key, '', (err: BusinessError, val: preferences.ValueType) => {
      if (err) {
        console.error(`${TAG} Failed to get value of ${key}. code =` + err.code + ", message =" + err.message);
        result.success('');
      }
      console.info(`${TAG} Succeeded in getting value of ${key}:${val}.`);
      result.success(val);
    })

  }

  setPrefs(key: string, value: string) {
    dataPreferences?.put(key, value, (err: BusinessError) => {
      if (err) {
        console.error(`${TAG} Failed to put value of ${key}. code =` + err.code + ", message =" + err.message);
        return;
      }
      console.info(`${TAG} Succeeded in putting value of ${key}.`);
    })
  }

  clearPrefs(key: string) {
    dataPreferences?.delete(key, (err: BusinessError) => {
      if (err) {
        console.error("Failed to delete the key 'startup'. code =" + err.code + ", message =" + err.message);
        return;
      }
      console.info(`Succeeded in deleting the key ${key}.`);
    })
  }
}

注意事項

1.雙端初始化methodChannel中的名稱必須保持一致猴抹,如 xxx.com/app.
2.arkTS側(cè)通過 result.success(val) 返回數(shù)據(jù)带族,該過程是異步的,故在 Dart 側(cè)需要使用 await 或者回調(diào)函數(shù)取值蟀给。
3.通信中默認只支持基礎(chǔ)的數(shù)據(jù)類型蝙砌,復(fù)雜類型的需要進行序列化或編解碼。
4.在Dart 側(cè)接收的數(shù)據(jù)為 dymanic 類型跋理,需要進行數(shù)據(jù)類型轉(zhuǎn)換择克。

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市前普,隨后出現(xiàn)的幾起案子肚邢,更是在濱河造成了極大的恐慌,老刑警劉巖拭卿,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骡湖,死亡現(xiàn)場離奇詭異,居然都是意外死亡峻厚,警方通過查閱死者的電腦和手機勺鸦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來目木,“玉大人换途,你說我怎么就攤上這事懊渡。” “怎么了军拟?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵剃执,是天一觀的道長。 經(jīng)常有香客問我懈息,道長肾档,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任辫继,我火速辦了婚禮怒见,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姑宽。我一直安慰自己遣耍,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布炮车。 她就那樣靜靜地躺著舵变,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瘦穆。 梳的紋絲不亂的頭發(fā)上纪隙,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音扛或,去河邊找鬼绵咱。 笑死,一個胖子當(dāng)著我的面吹牛熙兔,可吹牛的內(nèi)容都是我干的麸拄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼黔姜,長吁一口氣:“原來是場噩夢啊……” “哼拢切!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秆吵,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤淮椰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后纳寂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體主穗,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年毙芜,在試婚紗的時候發(fā)現(xiàn)自己被綠了忽媒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡腋粥,死狀恐怖晦雨,靈堂內(nèi)的尸體忽然破棺而出架曹,到底是詐尸還是另有隱情,我是刑警寧澤闹瞧,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布绑雄,位于F島的核電站,受9級特大地震影響奥邮,放射性物質(zhì)發(fā)生泄漏万牺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一洽腺、第九天 我趴在偏房一處隱蔽的房頂上張望脚粟。 院中可真熱鬧,春花似錦蘸朋、人聲如沸核无。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厕宗。三九已至画舌,卻和暖如春堕担,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背曲聂。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工霹购, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朋腋。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓齐疙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親旭咽。 傳聞我的和親對象是個殘疾皇子贞奋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容