首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Flutter 混合开发】与原生通信-MethodChannel

【Flutter 混合开发】与原生通信-MethodChannel

作者头像
老孟Flutter
发布于 2020-11-03 03:32:58
发布于 2020-11-03 03:32:58
1.8K00
代码可运行
举报
文章被收录于专栏:FlutterFlutter
运行总次数:0
代码可运行

Flutter 混合开发系列 包含如下:

  • 嵌入原生View-Android
  • 嵌入原生View-iOS
  • 与原生通信-MethodChannel
  • 与原生通信-BasicMessageChannel
  • 与原生通信-EventChannel
  • 添加 Flutter 到 Android Activity
  • 添加 Flutter 到 Android Fragment
  • 添加 Flutter 到 iOS

每个工作日分享一篇,欢迎关注、点赞及转发。

平台通信的3中方式

Flutter 与 Native 端通信有如下3个方法:

  • MethodChannel:Flutter 与 Native 端相互调用,调用后可以返回结果,可以 Native 端主动调用,也可以Flutter主动调用,属于双向通信。此方式为最常用的方式, Native 端调用需要在主线程中执行。
  • BasicMessageChannel:用于使用指定的编解码器对消息进行编码和解码,属于双向通信,可以 Native 端主动调用,也可以Flutter主动调用。
  • EventChannel:用于数据流(event streams)的通信, Native 端主动发送数据给 Flutter,通常用于状态的监听,比如网络变化、传感器数据等。
通信架构图

此图为官方的架构图

Flutter 与 Native 端通信是异步的。

通信与平台线程

Native 端主动发送数据给 Flutter时,Native 端代码需要在主线程中执行,Android 端从子线程跳转到主线程方式:

Kotlin 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Handler(Looper.getMainLooper()).post {
  
}

Java 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
new Handler(Looper.getMainLooper()).post(new Runnable() {
  @Override
  public void run() {
    
  }
});

如果可以获取到当前 Activity,也可以使用如下方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
activity.runOnUiThread {
   
}

iOS 端从子线程跳转到主线程方式:

Objective-C 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dispatch_async(dispatch_get_main_queue(), ^{
  
});

Swift 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DispatchQueue.main.async {
  
}

MethodChannel

Flutter 端

Flutter 端创建 MethodChannel 通道,用于与原生端通信:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var channel = MethodChannel('com.flutter.guide.MethodChannel');

com.flutter.guide.MethodChannel 是 MethodChannel 的名称,原生端要与之对应。

发送消息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var result = await channel.invokeMethod('sendData',{'name': 'laomeng', 'age': 18})
  • 第一个参数表示method,方法名称,原生端会解析此参数。
  • 第二个参数表示参数,类型任意,多个参数通常使用Map
  • 返回 Future,原生端返回的数据。

完整代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MethodChannelDemo extends StatefulWidget {
  @override
  _MethodChannelDemoState createState() => _MethodChannelDemoState();
}

class _MethodChannelDemoState extends State<MethodChannelDemo> {
  var channel = MethodChannel('com.flutter.guide.MethodChannel');

  var _data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          SizedBox(
            height: 50,
          ),
          RaisedButton(
            child: Text('发送数据到原生'),
            onPressed: () async {
              var result = await channel
                  .invokeMethod('sendData', {'name': 'laomeng', 'age': 18});
              var name = result['name'];
              var age = result['age'];
              setState(() {
                _data = '$name,$age';
              });
            },
          ),
          Text('原生返回数据:$_data')
        ],
      ),
    );
  }
}
Android 端

android 下创建 MethodChannelDemo

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.flutter.guide

import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel

/**
 * des:
 */
class MethodChannelDemo(messenger: BinaryMessenger): MethodChannel.MethodCallHandler {

    private var channel: MethodChannel

    init {
        channel = MethodChannel(messenger, "com.flutter.guide.MethodChannel")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        
    }
}

onMethodCall 方法在 Flutter 端调用 invokeMethod 方法回调,解析方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
    if (call.method == "sendData") {
        val name = call.argument("name") as String?
        val age = call.argument("age") as Int?

        var map = mapOf("name" to "hello,$name",
                "age" to "$age"
        )
        result.success(map)
    }
}
  • call.method 字符串就是 invokeMethod 方法传入的 method
  • call.argument 是 invokeMethod 传入的参数,由于 Flutter 端传入的是 Map,所以上面的解析按照 Map 解析。
  • result.success() 是返回给 Flutter 的结果。

Flutter 端解析:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var result = await channel
    .invokeMethod('sendData', {'name': 'laomeng', 'age': 18});
var name = result['name'];
var age = result['age'];

两端的解析要相互对应。

MainActivity 启动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MainActivity : FlutterActivity() {
    
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannelDemo(flutterEngine.dartExecutor.binaryMessenger)
    }
}
iOS 端

ios 下创建 MethodChannelDemo,按如下方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Flutter
import UIKit

public class MethodChannelDemo {
    
    init(messenger: FlutterBinaryMessenger) {
        let channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: messenger)
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "sendData") {
                if let dict = call.arguments as? Dictionary<String, Any> {
                    let name:String = dict["name"] as? String ?? ""
                    let age:Int = dict["age"] as? Int ?? -1
                    result(["name":"hello,\(name)","age":age])
                }
            }
        }
    }
}

AppDelegate 启动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    MethodChannelDemo(messenger: controller.binaryMessenger)
    GeneratedPluginRegistrant.register(with: self)
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

原生端主动发送消息给Flutter
Flutter 端接收数据
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@override
void initState() {
  super.initState();
  channel.setMethodCallHandler((call) {
    setState(() {
      _nativeData = call.arguments['count'];
    });
  });
}
Android 发送数据

原生端启动定时器,每隔一秒向 Flutter 发送数据,Android 端代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MethodChannelDemo(var activity: Activity, messenger: BinaryMessenger) : MethodChannel.MethodCallHandler {

    private var channel: MethodChannel
    private var count = 0

    init {
        channel = MethodChannel(messenger, "com.flutter.guide.MethodChannel")
        channel.setMethodCallHandler(this)
        startTimer()
    }


    fun startTimer() {
        var timer = Timer().schedule(timerTask {
            activity.runOnUiThread {
                var map = mapOf("count" to count++)
                channel.invokeMethod("timer", map)
            }
        }, 0, 1000)

    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        if (call.method == "sendData") {
            val name = call.argument("name") as String?
            val age = call.argument("age") as Int?

            var map = mapOf("name" to "hello,$name",
                    "age" to "$age"
            )
            result.success(map)
        }
    }
}

注意:Android 端发送数据要在主现场中调用,即:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
activity.runOnUiThread {
             var map = mapOf("count" to count++)
             channel.invokeMethod("timer", map)
         }

启动修改如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MainActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannelDemo(this,flutterEngine.dartExecutor.binaryMessenger)
        flutterEngine.plugins.add(MyPlugin())
    }
}
iOS 发送数据

iOS 端启动定时器代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Flutter
import UIKit

public class MethodChannelDemo {
    var count =  0
    var channel:FlutterMethodChannel
    init(messenger: FlutterBinaryMessenger) {
        channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: messenger)
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "sendData") {
                if let dict = call.arguments as? Dictionary<String, Any> {
                    let name:String = dict["name"] as? String ?? ""
                    let age:Int = dict["age"] as? Int ?? -1
                    result(["name":"hello,\(name)","age":age])
                }
            }
        }
        startTimer()
    }
    
    func startTimer() {
        var timer = Timer.scheduledTimer(timeInterval:1, target: self, selector:#selector(self.tickDown),userInfo:nil,repeats: true)
    }
    @objc func tickDown(){
        count += 1
        var args = ["count":count]
        channel.invokeMethod("timer", arguments:args)
    }
}

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老孟Flutter 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Flutter 混合开发】与原生通信-EventChannel
com.flutter.guide.EventChannel 是 EventChannel 的名称,原生端要与之对应。
老孟Flutter
2020/11/03
9750
【Flutter 混合开发】与原生通信-EventChannel
【Flutter 混合开发】与原生通信-BasicMessageChannel
com.flutter.guide.BasicMessageChannel 是 BasicMessageChannel 的名称,原生端要与之对应。
老孟Flutter
2020/11/03
1.2K0
【Flutter 混合开发】与原生通信-BasicMessageChannel
纯Flutter工程如何实现Flutter与原生互相通信
大多数同学都知道Flutter与原生通信MethodChannel或者EventChannel。这两个Channel在我之前的文章中有讲到区别和共同点,我们知道本质上都是MethodChannel。
老码小张
2020/05/28
2.1K0
纯Flutter工程如何实现Flutter与原生互相通信
鸿蒙Flutter实战:03-鸿蒙Flutter开发中集成Webview
如 使用flutter_inappwebview插件,在 pubspec.lock 文件中配置:
少湖说
2024/10/22
3400
【Flutter高级进阶实战 仿哔哩哔哩APP】(含代码)
Flutter 通过 MethodChannel、EventChannel 和 BasicMessageChannel 三种通道实现与原生平台的双向通信:
用户11659095
2025/06/29
1300
【Flutter 混合开发】嵌入原生View-Android
建议使用 Android Studio 进行开发,在 Android Studio 左侧 project tab下选中 android 目录下任意一个文件,右上角会出现 Open for Editing in Android Studio ,
老孟Flutter
2020/11/03
1.6K0
【Flutter 混合开发】嵌入原生View-Android
Flutter 混合开发(Android)Flutter跟Native相互通信
Flutter 作为混合开发,跟native端做一些交互在所难免,比如说调用原生系统传感器、原生端的网络框架进行数据请求就会用到 Flutter 调用android 及android 原生调用 Flutter的方法,这里就涉及到Platform Channels(平台通道)
conanma
2022/01/10
9730
flutter插件开发需要了解的EventChannel与MethodChannel
在flutter插件开发中,EventChannel与MethodChannel是两个不可避免的类。我们要了解它,最好先记住它通常用来干嘛。
老码小张
2020/01/08
6.8K0
[-Flutter插件篇 -] 认识MethodChannel
上次从一个路径插件看来一下Flutter中如何调用iOS和Android中的方法以及平台如何返回值给Flutter框架。今天就来详细讲讲MethodChannel是如何连同另一个世界的。 ---- 1
张风捷特烈
2020/04/30
2.6K0
[-Flutter插件篇 -] 认识MethodChannel
鸿蒙Flutter实战:06-使用ArkTs开发Flutter鸿蒙插件
本文讲述如何开发一个 Flutter 鸿蒙插件,如何实现 Flutter 与鸿蒙的混合开发,以及双端消息通信。
少湖说
2024/10/22
3880
鸿蒙Flutter实战:06-使用ArkTs开发Flutter鸿蒙插件
Flutter实战:手把手教你写Flutter Plugin
如果你对移动端有所关注,那么你一定会听说过Flutter。得益于Google,Flutter一经推出便得受到了广泛关注。很多开发者跃跃欲试,国内部分大厂,诸如美团、闲鱼等团队已经开始了Flutter实践之旅了。笔者也是蹭了一波热度,学习了一下Flutter。Flutter虽然真香,但目前社区显然还是很不健全,像微信SDK、支付宝等第三方SDK都无法在Flutter项目上直接使用。想要使用这些SDK就曲线救国了。 本文并不探讨如何发布一个Flutter Plugin,只谈如何实现Plugin。下面我将以我的开源项目fluwx为例,手把手教你如何写Flutter Plugin。
JarvanMo
2018/10/10
5.9K0
Flutter实战:手把手教你写Flutter Plugin
【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 MethodChannel 通信 )
本博客与 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 在 Flutter 端实现 MethodChannel 通信 ) 博客相对应 , 该博客中开发 Flutter 的 Dart 端 ;
韩曙亮
2023/03/29
9310
Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信。
AndroidTraveler
2019/04/09
9800
Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
从零开始的Flutter之旅: MethodChannel
在flutter_github有这么一个场景:通过authorization认证方式进行登录。而authorization的具体登录形式是,通过跳转一个网页链接进行github授权登录,成功之后会携带对应的code到指定客户端中,然后客户端可以通过这个code来进行oauth授权登录,成功之后客户端可以拿到该账户的token,所以之后的github操作都可以通过该token来进行请求。由于token是有时效性,同时也可以手动解除授权,所以相对于在客户端进行账户密码登录来说更加安全。
Rouse
2020/07/13
1.4K0
Flutter 混合开发】嵌入原生View-iOS
建议使用 Xcode 进行开发,在 Android Studio 左侧 project tab下选中 ios 目录下任意一个文件,右上角会出现 Open iOS module in Xcode ,
老孟Flutter
2020/11/03
1.2K0
Flutter 混合开发】嵌入原生View-iOS
[-Flutter插件篇 -] 从自定义插件开始说起
Flutter可以为你提供一个强大华丽简洁高效的跨平台UI界面, 但无论外表多么绚丽美女,没有内在也只是空壳,你会喜欢她吗?(还用问,当然会) 使用插件可以让Flutter轻松与当前平台进行联系,
张风捷特烈
2020/04/30
2K0
[-Flutter插件篇 -] 从自定义插件开始说起
Flutter与原生通信
这三种类型的Channel都是全双向通信,即A<=>B,flutter可以主动发送消息给Native端,并且Native接收到消息后可以做出回应,同样,Native端可以主动发送消息给flutter端,flutter端接收数据后给Native端。
愤怒的小鸟
2021/04/07
2.8K0
【拥抱鸿蒙】Flutter+Cursor轻松打造HarmonyOS应用(一)
在移动应用开发领域,Flutter以其出色的跨平台能力和高效的开发体验赢得了众多开发者的青睐,是许多移动开发者混合开发的首选。
郑知鱼
2025/05/26
7310
【拥抱鸿蒙】Flutter+Cursor轻松打造HarmonyOS应用(一)
Flutter与原生工程的混合开发
上述这两大类都是可以实现的,技术层面没有任何问题。但是我并不建议在Flutter页面和原生页面之间来回穿插切换,原因如下:
拉维
2021/11/19
1.5K0
Flutter 如何混编原生功能
依托于与 Skia 的深度定制及优化,Flutter 给我们提供了很多关于渲染的控制和支持,能够实现绝对的跨平台应用层渲染一致性。但对于一个应用而言,除了应用层视觉显示和对应的交互逻辑处理之外,有时还需要原生操作系统(Android、iOS)提供的底层能力支持。比如,我们前面提到的数据持久化,以及推送、摄像头硬件调用等。
网罗开发
2021/03/17
2.7K0
推荐阅读
相关推荐
【Flutter 混合开发】与原生通信-EventChannel
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档