Flutter 混合開發 (交互通訊)

上篇咱們介紹了 Flutter 模塊集成到已有的項目工程,接下來咱們看看 Native 跟 Flutter 間的交互問題。ios

交互通訊objective-c

Flutter 與原生之間的通訊依賴靈活的消息傳遞方式:app

1,Flutter 部分經過平臺通道將消息發送到其應用程序的所在的宿主環境(原生應用)。async

2,宿主環境經過監聽平臺通道,接收消息。而後它會調用平臺的 API,響應 Flutter 發送的消息。ide

Flutter主動 調用 宿主環境設計

在 Flutter 中經過 MethodChannel 的 API 能夠發送與方法相對於的消息,宿主環境 iOS 中經過 FlutterMethodChannel 接受方法的調用並返回結果。code

Flutter 須要引入 services.dart 模塊才能夠使用 MethodChannelorm

import 'package:flutter/services.dart';

Flutter 中的調用代碼事件

const methodChannel = const MethodChannel("com.pages.flutter/call_native");
RaisedButton(
        child: Text("call_native_method_no_params"),
        onPressed: (){
                 methodChannel.invokeMethod("call_native_method_no_params",null);
        },
      ),
      RaisedButton(
        child: Text("call_native_method_params"),
        onPressed: (){
          Map<String,String> params = {"params":"flutter params"};
          methodChannel.invokeMethod("call_native_method_params",params);
        },
      ),
      RaisedButton(
        child: Text("call_native_method_native_result_callback"),
        onPressed: (){
          _nativeCallbackWithParams();
        },
      ),
      Text(_content,style: TextStyle(color: Colors.red),)
Future<Null> _nativeCallbackWithParams() async{
  dynamic result;
  try {
      result = await methodChannel.invokeMethod(
            "call_native_method_native_result_callback", null);
  } on PlatformException catch (e) {
    result = "Failed to get params: '${e.message}'.";
  }
  setState(() {
    _content = result;
  });
}

iOS 中的調用代碼get

FlutterViewController* flutterViewController = [[FlutterViewController alloc] init];
flutterViewController.fd_prefersNavigationBarHidden = YES;
FlutterMethodChannel * messageChannel = [FlutterMethodChannel methodChannelWithName:@"com.pages.flutter/call_native" binaryMessenger:flutterViewController];
[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
        NSLog(@"flutter call native:\n method=%@ \n arguments = %@",call.method,call.arguments);
        if ([call.method isEqualToString:@"call_native_method_native_result_callback"]) {
            if (result) {
                result(@"flutter hello");
            }
        }else if([call.method isEqualToString:@"call_native_method_pop_flutter_nav"]){
            [weakSelf.navigationController popViewControllerAnimated:YES];
        }
    }];
[self.navigationController pushViewController:flutterViewController animated:YES];

分別看下控制檯輸出:

flutter call native:
method=call_native_method_no_params 
arguments = (null)
flutter call native:
method=call_native_method_params 
arguments = {
  params = "flutter params";
}

第三個事件會在 Flutter 頁面顯示flutter hello 該值由宿主環境返回。

注意:這裏有個設計上的細節,上節提到過就是導航欄的問題,由於宿主環境有個導航欄,而 Flutter 自身也有導航欄,出現了矛盾,到底咱們應該保留宿主環境的,仍是 Flutter 頁面使用自身,隱藏宿主環境的導航欄。我我的以爲後則更合理,Flutter 頁面更瞭解本身導航欄具體功能、主題、交互及顯示,咱們只須要處理點擊返回按鈕 pop 回到宿主環境中,以下:

appBar: AppBar(
      title: Text('Flutter Page') ,
      leading: IconButton(icon: Icon(Icons.arrow_back_ios), onPressed:()=>methodChannel.invokeMethod("call_native_method_pop_flutter_nav",null)),
    ),

咱們只須要在宿主環境中監聽到該事件後調用導航的 pop 功能。

宿主環境主動調用 Flutter

通常能夠用做宿主環境爲 Flutter 提供參數

EventChannel 是 Flutter 監聽宿主環境的 API ,FlutterEventChannel 是 iOS 宿主環境與 Flutter 交互平臺通道的 API 。

Flutter 代碼片斷

const EventChannel eventChannel = const EventChannel('com.pages.flutter/call_flutter');
@override
void initState(){
  super.initState();
 eventChannel.receiveBroadcastStream(12345).listen(_onEvent,onError: _onError);
}

void _onEvent(Object event){
  setState(() {
    _content = event.toString();
  });
}

void _onError(Object error){
  setState(() {
    _content = error.toString();
  });
}

iOS 宿主環境代碼片斷

NSString *eventChannelName = @"com.pages.flutter/call_flutter";
FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:eventChannelName binaryMessenger:flutterViewController];
[eventChannel setStreamHandler:self];
- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
    if (events) {
        events(@"hi flutter");
    }
    return nil;
}

- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    return nil;
}

兩端交互通訊方式就是這樣的,這裏也只是介紹了他們通訊的方式,具體如何優雅的封裝、規範交互流程還須要咱們本身去考慮下。

相關文章
相關標籤/搜索