22.原生項目和Flutter的混合開發(三)

目錄傳送門:《Flutter快速上手指南》先導篇java

經過閱讀 混合開發(一)混合開發(二) ,相信你已經讓一個 原生 + Flutetr 的混合應用運行起來了。git

恭喜你 🎉🎉🎉!github

如今,你可能遇到了 Flutter代碼 和 原生代碼 以前沒法互相調用的難題。bash

由於 Flutter 做爲獨立於原生 Android 的一套開發框架,確定是不能直接互相調用和愉快的交換信息的。架構

如今,來看看 Flutter 是如何解決這些問題的。框架

1.Platform Channels

Flutter 使用 Platform Channels 架構來實現 Flutter 和 原生 之間的通訊。異步

上圖是其中 MethodChannel 的架構示意圖,Flutter 能夠經過 MethodChannel 異步的發送和接收信息。async

MethodChannel 是通過封裝的比較方便的通訊方式,Flutter 官網的例子也是經過 MethodChannel 來實現的。ide

Platform Channels 僅容許如下幾種的數據類型在通訊中使用:函數

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool
int java.lang.Integer NSNumber numberWithInt
int, if 32 bits not enough java.lang.Long NSNumber numberWithLong
double java.lang.Double NSNumber numberWithDouble
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes
Int32List int[] FlutterStandardTypedData typedDataWithInt32
Int64List long[] FlutterStandardTypedData typedDataWithInt64
Float64List double[] FlutterStandardTypedData typedDataWithFloat64
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

2.如何使用 MethodChannel

MethodChannel 經過特定的通道,來創建起 Flutter 和 Native 之間通訊橋樑。

固然,咱們須要在 Flutter 和 Native 兩端都須要定義相同的通道。

2.1 第一步:定義通訊通道

  • Flutter 端:

    先導入 import 'package:flutter/services.dart'; 包,而後建立一個 MethodChannel。

    const channel = MethodChannel('foo');
    複製代碼
  • Native - Android 端:

    MethodChannel channel = new MethodChannel(flutterView, "foo");複製代碼
  • Native - iOS 端:

    let channel = FlutterMethodChannel(
      name: "foo", binaryMessenger: flutterView)
    複製代碼

創建一個通訊通道的方式很簡單,只須要使用相同的名稱(好比上面例子中的 "foo")建立 MethodChannel 就行。

在一個大型的項目中。你可能會須要創建不少的通訊通道,因此建議統一的管理這些通訊通道。

2.2 Flutter to Native

創建好通訊通道,來看看如何讓 Flutter 主動和 Native 通訊。

  • Flutter 端:

    final String greeting = await channel.invokeMethod('bar', 'world');
    print(greeting);複製代碼

    經過 invokeMethod(<標識>, <數據>) 函數能夠主動發起和 Native 的一次通訊,且可以得到響應,容許的數據類型就是前面表格中列出的數據類型。

    固然,爲了避免阻塞 UI,你須要在異步中進行。

  • Native - Android 端:

    channel.setMethodCallHandler((methodCall, result) -> {
        if (methodCall.method.equals("bar")) {
            result.success("success, " + methodCall.arguments);
        }
    });複製代碼

    在 Native 端,經過爲 MethodChannel 設置一個處理器 MethodCallHandler

    當 Flutter 向 Native 發起通訊時,可以回調處理器中的 onMethodCall() 函數。

    在該回調中,可以經過 MethodCall 獲取 Flutter 發送過來的信息,經過 MethodChannel.Result 來向 Flutter 發送響應結果。

  • Native - iOS 端:

    channel.setMethodCallHandler {
      (call: FlutterMethodCall, result: FlutterResult) -> Void in
      switch (call.method) {
      case "bar": result("Hello, \(call.arguments as! String)")
      default: result(FlutterMethodNotImplemented)
      }
    }
    複製代碼

2.3 Native to Flutter

  • Flutter 端:

    設置接收 Native 信息的處理器:

    channel.setMethodCallHandler((MethodCall call) async {
      switch (call.method) {
        case 'bar':
          return 'Hello, ${call.arguments}';
        case 'baz':
          throw PlatformException(code: '400', message: 'This is bad');
        default:
          throw MissingPluginException();
      }
    })
    複製代碼

    經過 setMethodCallHandler 函數設置一個 Future<dynamic> handler(MethodCall call) 函數。

    該函數會在接收到 Native 信息時被調用,從 MethodCall 中可以得到 Native 發送過來的數據。

    最後的 return 環節能夠返回數據給 Native。

  • Native - Android 端:

    channel.invokeMethod("bar", "message", new MethodChannel.Result
        @Override
        public void success(@Nullable Object o) {
            // 發送成功時回調
        }
        @Override
        public void error(String s, @Nullable String s1, @Nullable
            // 發送失敗時回調
        }
        @Override
        public void notImplemented() {
            // 若是該通道在Flutter端未實現,會回調這裏
        }
    });
    複製代碼

    第一個參數是 Flutter 端經過 call.method 得到的標示。

    第二個參數是須要發送的數據。

    第三個參數用於監聽通訊是完成狀態。

  • Native - iOS 端:

    channel.invokeMethod(name, arguments: value) {
      (result: Any?) -> Void in
      if let error = result as? FlutterError {
        os_log("%@ failed: %@", type: .error, name, error.message!)
      } else if FlutterMethodNotImplemented.isEqual(result) {
        os_log("%@ not implemented", type: .error, name)
      } else {
        os_log("%@", type: .info, result as! NSObject)
      }
    }複製代碼

目錄傳送門:《Flutter快速上手指南》先導篇

如何找到我?

傳送門:CoorChice 的主頁

傳送門:CoorChice 的 Github

相關文章
相關標籤/搜索