flutter与原生通信的方式简介

Flutter和原生之间进行通信可以通过以下几种方式:

  1. Flutter MethodChannel:Flutter提供了MethodChannel来实现Flutter与原生平台的双向方法调用。我们可以在Flutter中创建一个MethodChannel对象,并定义方法的名称和参数。然后在原生代码中注册相应的方法处理程序,当Flutter调用该方法时,原生代码会执行相应的操作,并返回结果给Flutter。

  2. Flutter EventChannel:EventChannel用于在Flutter和原生之间传递事件流。我们可以在Flutter中创建一个EventChannel对象,并定义事件的名称和参数。然后在原生代码中监听该事件,并在特定条件下发送事件给Flutter。

  3. PlatformView:如果你需要在Flutter中使用原生控件或视图,可以使用PlatformView。它允许我们在Flutter中嵌入原生视图,并与其进行交互。

  4. Flutter Plugin:如果需要更复杂的功能或者想要封装一些原生功能为Flutter插件,可以创建一个Flutter插件。Flutter插件允许我们在Flutter和原生之间建立更高级的通信机制,并提供一致的API给Flutter开发者使用。

这些是常见的Flutter和原生通信方式,具体的选择取决于实际需求和场景。

下面是简单的demo实现:

首先是MethodChannel的方式:

在Flutter中,可以使用MethodChannel来实现与原生平台(如安卓和iOS)的通信。下面是一个简单的代码示例:

首先,在Flutter端创建一个MethodChannel对象,并定义与原生平台通信的方法:

首先dart代码实现:
 import 'package:flutter/services.dart';

// 创建MethodChannel对象
MethodChannel _channel = MethodChannel('com.example.channel');

// 定义与原生平台通信的方法
Future<void> sendMessageToNative(String message) async {
  try {
    // 调用原生平台的方法
    await _channel.invokeMethod('sendMessage', {'message': message});
  } catch (e) {
    print('Error: $e');
  }
}

然后,在原生平台的代码中注册MethodChannel,并处理Flutter端发送的消息:

在安卓端(Java)的代码示例:
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

public class MainActivity extends FlutterActivity {
 private static final String CHANNEL = "com.example.channel";

// 创建MethodChannel对象
 private MethodChannel methodChannel;

 @Override
 public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
   super.configureFlutterEngine(flutterEngine);

   // 注册MethodChannel
   methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
   //接受flutter消息
   methodChannel.setMethodCallHandler(new MethodCallHandler() {
     @Override
     public void onMethodCall(MethodCall call, Result result) {
        if (call.method.equals("sendMessage")) {
          String message = call.argument("message");
          // 处理Flutter端发送的消息
          handleSendMessage(message);
          result.success(null); // 返回结果给Flutter端
         } else {
           result.notImplemented();
         }
       }
     });
/*
  //发送给flutter消息
   String message = "Hello from Android";
  // 发送消息给Flutter端
    methodChannel.invokeMethod("sendMessage", message);
*/
 }

 private void handleSendMessage(String message) {
   // 处理接收到的消息
   System.out.println("Received message from Flutter: " + message);
 }
}
在iOS端(Objective-C)的代码示例:

#import "AppDelegate.h"
#import <Flutter/Flutter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* flutterViewController = (FlutterViewController*)self.window.rootViewController;

  // 注册MethodChannel
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"com.example.channel"
            binaryMessenger:flutterViewController.binaryMessenger];

  [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([call.method isEqualToString:@"sendMessage"]) {
      NSString* message = call.arguments[@"message"];
      // 处理Flutter端发送的消息
      [self handleSendMessage:message];
      result(nil); // 返回结果给Flutter端
    } else {
      result(FlutterMethodNotImplemented);
    }
  }];

/*
   // 发送消息给Flutter端
  [channel invokeMethod:@"sendMessage" arguments:message];
*/
 
 return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)handleSendMessage:(NSString*)message {
  // 处理接收到的消息
  NSLog(@"Received message from Flutter: %@", message);
}

@end

//
//
//

然后是使用EventChannel进行通信

dart代码:

import 'package:flutter/services.dart';

// 创建EventChannel对象
EventChannel _eventChannel = EventChannel('com.example.channel');

// 定义与原生平台通信的事件流
Stream<dynamic> receiveMessageFromNative() {
  // 监听原生平台发送的事件
  return _eventChannel.receiveBroadcastStream();
}
安卓代码:
import io.flutter.plugin.common.EventChannel;

public class MainActivity extends FlutterActivity {
  private static final String CHANNEL = "com.example.channel";

  @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    super.configureFlutterEngine(flutterEngine);

    // 注册EventChannel
    new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
        .setStreamHandler(new EventChannel.StreamHandler() {
          private EventChannel.EventSink eventSink;

          @Override
          public void onListen(Object arguments, EventChannel.EventSink sink) {
            eventSink = sink;
            
            // 发送事件给Flutter端
            sendMessageToFlutter("Hello from Android");
          }

          @Override
          public void onCancel(Object arguments) {
            eventSink = null;
          }
          
          private void sendMessageToFlutter(String message) {
            if (eventSink != null) {
              eventSink.success(message); // 发送事件给Flutter端
            }
          }
        });
  }
}
iOS代码:
#import "AppDelegate.h"
#import <Flutter/Flutter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* flutterViewController = (FlutterViewController*)self.window.rootViewController;

  // 注册EventChannel
  FlutterEventChannel* channel = [FlutterEventChannel
      eventChannelWithName:@"com.example.channel"
           binaryMessenger:flutterViewController.binaryMessenger];

  [channel setStreamHandler:self];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

#pragma mark - FlutterStreamHandler

- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
  // 发送事件给Flutter端
  [self sendMessageToFlutter:@"Hello from iOS" eventSink:eventSink];
  return nil;
}

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

- (void)sendMessageToFlutter:(NSString *)message eventSink:(FlutterEventSink)eventSink {
  if (eventSink) {
    eventSink(message); // 发送事件给Flutter端
  }
}

@end
然后是使用PlatformView与原生进行通信

它本质上也是用的MethodChannel或者EventChannel进行通信

首先,在Flutter端创建一个PlatformView,并定义与原生通信的方法:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class NativeView extends StatefulWidget {
  @override
  _NativeViewState createState() => _NativeViewState();
}

class _NativeViewState extends State<NativeView> {
  // 创建MethodChannel对象
  MethodChannel _methodChannel = MethodChannel('com.example.native_view');

  // 定义与原生通信的方法
  Future<void> sendMessageToNative(String message) async {
    try {
      // 调用原生平台的方法
      await _methodChannel.invokeMethod('sendMessage', {'message': message});
    } catch (e) {
      print('Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return AndroidView(
      viewType: 'com.example.native_view',
      creationParamsCodec: const StandardMessageCodec(),
      onPlatformViewCreated: (int id) {
        // 原生视图创建完成后,可以进行一些初始化操作
      },
    );
  }
}

然后,在原生平台的代码中创建并注册PlatformView,并处理Flutter端发送的消息:

在安卓端(Java)的代码示例:
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;

public class MainActivity extends FlutterActivity {
  private static final String CHANNEL = "com.example.native_view";

  @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    super.configureFlutterEngine(flutterEngine);

    // 注册PlatformView
    flutterEngine.getPlatformViewsController().getRegistry().registerViewFactory(CHANNEL, new NativeViewFactory());

    // 创建MethodChannel对象
    MethodChannel methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
    methodChannel.setMethodCallHandler((call, result) -> {
      if (call.method.equals("sendMessage")) {
        String message = call.argument("message");
        // 处理Flutter端发送的消息
        handleSendMessage(message);
        result.success(null); // 返回结果给Flutter端
      } else {
        result.notImplemented();
      }
    });
  }

  private void handleSendMessage(String message) {
    // 处理接收到的消息
    System.out.println("Received message from Flutter: " + message);
  }
}
在iOS端(Objective-C)的代码示例
#import "AppDelegate.h"
#import <Flutter/Flutter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  FlutterViewController* flutterViewController = (FlutterViewController*)self.window.rootViewController;

  // 注册PlatformView
  [flutterViewController.platformViewRegistry registerViewFactory:@"com.example.native_view" withBlock:^(id<FlutterBinaryMessenger> messenger, id arguments) {
    return [[NativeView alloc] initWithMessenger:messenger];
  }];

  // 创建MethodChannel对象
  FlutterMethodChannel* methodChannel = [FlutterMethodChannel methodChannelWithName:@"com.example.native_view" binaryMessenger:flutterViewController.binaryMessenger];
  [methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([call.method isEqualToString:@"sendMessage"]) {
      NSString* message = call.arguments[@"message"];
      // 处理Flutter端发送的消息
      [self handleSendMessage:message];
      result(nil); // 返回结果给Flutter端
    } else {
      result(FlutterMethodNotImplemented);
    }
  }];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)handleSendMessage:(NSString*)message {
  // 处理接收到的消息
  NSLog(@"Received message from Flutter: %@", message);
}

@end

//
//
//

最后是使用Flutter Plugin进行通信

首先,在Flutter端创建一个Flutter插件,并定义与原生通信的方法:

 import 'package:flutter/services.dart';

class MyPlugin {
  static const MethodChannel _channel = MethodChannel('my_plugin');

  static Future<String> getPlatformVersion() async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static Future<void> sendMessageToNative(String message) async {
    await _channel.invokeMethod('sendMessage', {'message': message});
  }
}

然后,在原生平台(安卓或iOS)的代码中实现Flutter插件的功能:

在安卓端(Java)的代码示例:
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

public class MyPlugin implements FlutterPlugin, MethodCallHandler {
  private MethodChannel methodChannel;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    methodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "my_plugin");
    methodChannel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      String version = "Android " + android.os.Build.VERSION.RELEASE;
      result.success(version);
    } else if (call.method.equals("sendMessage")) {
      String message = call.argument("message");
      // 处理Flutter端发送的消息
      handleSendMessage(message);
      result.success(null);
    } else {
      result.notImplemented();
    }
  }

  private void handleSendMessage(String message) {
    // 处理接收到的消息
    System.out.println("Received message from Flutter: " + message);
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    methodChannel.setMethodCallHandler(null);
  }
}
在iOS端(Objective-C)的代码示例:
#import <Flutter/Flutter.h>

@interface MyPlugin : NSObject<FlutterPlugin>
@end

@implementation MyPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
 FlutterMethodChannel* channel = [FlutterMethodChannel
     methodChannelWithName:@"my_plugin"
           binaryMessenger:[registrar messenger]];
 MyPlugin* instance = [[MyPlugin alloc] init];
 [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
 if ([call.method isEqualToString:@"getPlatformVersion"]) {
   NSString* version = [NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]];
   result(version);
 } else if ([call.method isEqualToString:@"sendMessage"]) {
   NSString* message = call.arguments[@"message"];
   // 处理Flutter端发送的消息
   [self handleSendMessage:message];
   result(nil);
 } else {
   result(FlutterMethodNotImplemented);
 }
}

- (void)handleSendMessage:(NSString*)message {
 // 处理接收到的消息
 NSLog(@"Received message from Flutter: %@", message);
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,846评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,146评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,789评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,656评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,467评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,870评论 3 389
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,500评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,790评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,828评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,628评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,449评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,881评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,077评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,376评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,879评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,089评论 2 338

推荐阅读更多精彩内容