Flutter MethodChannel的使用及原理解析

Dart和原生通信

一次典型的方法调用过程类似网络调用,由作为客户端的 Flutter,通过方法通道向作为服务端的原生代码宿主发送方法调用请求,原生代码宿主在监听到方法调用的消息后,调用平台相关的 API 来处理 Flutter 发起的请求,最后将处理完毕的结果通过方法通道回发至 Flutter。调用过程如下图所示:

image

1. 基本用法

以跳转应用市场为例

//声明MethodChannel
const platform = MethodChannel('channelName');

//处理按钮点击
handleButtonClick() async{
   
  int result;
  //异常捕获
  try {
   
    //异步等待方法通道的调用结果
    result = await platform.invokeMethod('openAppMarket');
  }
  catch (e) {
   
    result = -1;
  }
  print("Result:$result");
}

1.1 Android端实现
MainActivity.java

public class MainActivity extends FlutterActivity {
   
    MethodChannel methodChannel;

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
   
        super.configureFlutterEngine(flutterEngine);
        methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "channelName");
        methodChannel.setMethodCallHandler((call, result) -> {
   
            //判断方法名是否支持
            if(call.method.equals("openAppMarket")) {
   
                try {
   
                    //应用市场URI
                    Uri uri = Uri.parse("market://details?id=com.hangchen.example.flutter_module_page.host");
                    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    //打开应用市场
                    startActivity(intent);
                    //返回处理结果
                    result.success(0);
                } catch (Exception e) {
   
                    //打开应用市场出现异常
                    result.error("UNAVAILABLE", "没有安装应用市场", null);
                }
            }else {
   
                //方法名暂不支持
                result.notImplemented();
            }
        });
    }
}

1.2 iOS端实现
AppleDelegate.m


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   
  //创建命名方法通道
  FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"samples.chenhang/utils" binaryMessenger:(FlutterViewController *)self.window.rootViewController];
  //往方法通道注册方法调用处理回调
  [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
   
    //方法名称一致
    if ([@"openAppMarket" isEqualToString:call.method]) {
   
      //打开App Store(本例打开微信的URL)
      [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/xy/app/foo/id414478124"]];
      //返回方法处理结果
      result(@0);
    } else {
   
      //找不到被调用的方法
      result(FlutterMethodNotImplemented);
    }
  }];
  ...
}

2. 原理分析

Dart这边的MethodChannel类,有几个重要的成员变量:

  /// 方法通道的名字 not null
  final String name;

  /// 信息的编解码器 not null
  final MethodCodec codec;

  /// 用来发送消息的messenger
  /// 未设定的话就用默认的
  BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger;
  final BinaryMessenger? _binaryMessenger;

2.1 调用invokeMethod来获取通信结果

Future<T?> _invokeMethod<T>(String method, {
    required bool missingOk, dynamic arguments }) async {
   
    final ByteData? result = await binaryMessenger.send(
      name,
      codec.encodeMethodCall(MethodCall(method, arguments)),
    );
    if (result == null) {
   
      if (missingOk) {
   
        return null;
      }
      throw MissingPluginException('No implementation found for method $method on channel $name');
    }
    return codec.decodeEnvelope(result) as T?;
  }

先是将我们要调用的方法名构造了一个MethodCall,然后用codec编码,之后通过binaryMessenger发送了一条消息,调用结果会被封装成一个ByteData,然后用codec解码。

2.2 StandartMethodCodec
codec默认是一个StandardMethodCodec,看下它的encodeMethodCall方法做了什么

@override
ByteData encodeMethodCall(MethodCall call) {
   
    final WriteBuffer buffer = WriteBuffer();
    messageCodec.writeValue(buffer, call.method);
    messageCodec.writeValue(buffer, call.arguments);
    return buffer.done();
}

构造了一个WriteBuffer,然后将方法名和buffer传进messageCodec

void writeValue(
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
FlutterMethodChannel是一种在Flutter和原生平台(如iOS)之间进行通信的机制。它允许Flutter应用程序调用原生平台上的方法,并且还可以让原生平台调用Flutter的方法。 在iOS上使用MethodChannel,首先需要在原生平台(Objective-C或Swift)的代码中创建一个MethodChannel实例。这个实例需要一个唯一的通道名称,以便Flutter可以识别它。然后,可以使用MethodChannel实例来注册方法,并指定一个方法名称和一个回调函数来处理该方法被调用时的逻辑。 在Flutter应用程序中,可以使用MethodChannel的实例来调用原生平台上注册的方法。可以指定方法名称和传递参数(如果需要)。MethodChannel会将这个方法调用发送到原生平台,并等待原生平台返回结果。一旦结果返回,可以在Flutter端处理它。 使用MethodChannel时需要注意一些事项。首先,MethodChannel只能传递符合平台限制的数据类型,如字符串、数字、布尔值等。如果需要传递复杂的数据结构,可以将数据转换为平台能够识别的格式(如JSON),然后再进行传递。其次,MethodChannel是一种异步通信机制,所以在处理方法调用时需要考虑异步操作和结果处理的情况。 总的来说,FlutterMethodChannel是一种强大而灵活的机制,可以实现Flutter应用程序与原生平台之间的双向通信。它为开发人员提供了在Flutter和iOS之间传递方法调用和数据的能力,可以实现更高级的功能和交互体验。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值