Flutter 核心技术与实战
陈航
前美团点评高级技术专家
42432 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 48 讲
Flutter 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

26 | 如何在Dart层兼容Android/iOS平台特定实现?(一)

原生代码处理方法调用请求时需要确保回调过程在原生系统的UI线程中执行
接口调用必须发生在主线程
执行结果通过消息通道回传至Flutter
原生代码宿主注册对应方法实现、响应并处理调用请求
请求经由唯一标识符指定的方法通道到达原生代码宿主
Flutter发起方法调用请求
openAppMarket支持传入AppID和包名
扩展方法通道示例
使用StandardMessageCodec对通道中传输的信息进行序列化和反序列化
Android、iOS和 Dart平台间的常见数据类型转换
通过URL打开应用市场
响应方法请求
设置方法处理回调
创建与调用方标识符一样的方法通道
在AppDelegate中添加相关逻辑
增加try-catch捕获可能的异常
打开应用市场的Intent
响应方法请求
设置方法处理回调
创建与调用方标识符一样的方法通道
在MainActivity中添加相关逻辑
异常捕获
异步等待方法通道的调用结果
Flutter通过指定方法名发起方法调用请求
唯一字符串标识符构造命名通道
非线程安全
调用过程
实现与原生代码的交互
逻辑层的原生能力复用问题
Flutter提供的解决方案
思考题
数据类型转换
iOS端实现方法调用的响应
Android端实现方法调用的响应
Flutter实现方法调用请求
方法通道

该思维导图由 AI 生成,仅供参考

你好,我是陈航。
在上一篇文章中,我与你介绍了在 Flutter 中实现数据持久化的三种方式,即文件、SharedPreferences 与数据库。
其中,文件适用于字符串或者二进制流的数据持久化,我们可以根据访问频次,决定将它存在临时目录或是文档目录。而 SharedPreferences 则适用于存储小型键值对信息,可以应对一些轻量配置缓存的场景。数据库则适用于频繁变化的、结构化的对象存取,可以轻松应对数据的增删改查。
依托于与 Skia 的深度定制及优化,Flutter 给我们提供了很多关于渲染的控制和支持,能够实现绝对的跨平台应用层渲染一致性。但对于一个应用而言,除了应用层视觉显示和对应的交互逻辑处理之外,有时还需要原生操作系统(Android、iOS)提供的底层能力支持。比如,我们前面提到的数据持久化,以及推送、摄像头硬件调用等。
由于 Flutter 只接管了应用渲染层,因此这些系统底层能力是无法在 Flutter 框架内提供支持的;而另一方面,Flutter 还是一个相对年轻的生态,因此原生开发中一些相对成熟的 Java、C++ 或 Objective-C 代码库,比如图片处理、音视频编解码等,可能在 Flutter 中还没有相关实现。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Flutter的方法通道(Method Channel)机制为Dart和原生代码之间的交互提供了便捷的方式,使得Flutter应用能够轻松访问Android和iOS平台的底层能力。通过方法通道,Flutter可以调用原生系统底层能力和代码库,实现诸如数据持久化、推送、摄像头硬件调用等功能。本文通过示例展示了在Flutter中实现与原生代码的交互,包括发起方法调用请求、在Android和iOS平台上完成对应的接口实现,以及处理和响应方法调用请求的过程。此外,还介绍了在不同平台间的常见数据类型转换。这些内容有助于开发者理解Flutter的跨平台特性和与原生代码的交互方式。方法通道解决了逻辑层的原生能力复用问题,使得Flutter能够通过轻量级的异步方法调用,实现与原生代码的交互。需要注意的是,方法通道是非线程安全的,因此所有接口调用必须发生在主线程。文章最后提出了一个思考题,鼓励读者扩展方法通道示例,支持传入AppID和包名,以实现跳转到任意一个App的应用市场。这篇文章内容丰富,对于想要深入了解Flutter与原生代码交互的开发者来说,是一篇值得阅读的技术文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Flutter 核心技术与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(17)

  • 最新
  • 精选
  • 和小胖
    思考题: flutter 端: // 处理按钮点击 handleButtonClick() async { int result; // 异常捕获 try { // 异步等待方法通道的调用结果 result = await platform.invokeMethod('openAppMarket', <String, dynamic>{ 'appId': "com.xxx.xxx", 'packageName': "xxx.com.xxx", }); } catch (e) { result = -1; } print("Result:$result"); } Android 端: if (call.method == "openAppMarket") { if (call.hasArgument("appId")) { //获取 appId call.argument<String>("appId") } if (call.hasArgument("packageName")) { //获取包名 call.argument<String>("packageName") } }

    作者回复: 厉害👍

    2019-10-14
    6
  • 矮个子先生😝
    看了下Flutter提供的api,动手实现了下,native调flutter的方法 Future<String> nativeCallFlutter(int a) async { print('success $a'); return 'success'; } platform.setMethodCallHandler((MethodCall call) async { if (call.method == 'nativeCallFlutter') { return await nativeCallFlutter(call.arguments); } return 'none'; }); 在iOS端调用: [channel invokeMethod:@"nativeCallFlutter" arguments:@1 result:^(id _Nullable result) { NSLog(@"result = %@",result); }];

    作者回复: 赞,方法通道是双向的,既支持Dart调Native,也支持Native调Dart。第31节会讲具体的实践

    2019-08-27
    4
  • 寂寞不点烟
    而原生代码在处理方法调用请求时,如果涉及到异步或非主线程切换,需要确保回调过程是在原生系统的 UI 线程(也就是 Android 和 iOS 的主线程)。在Android中UI现线程不一定是主线程。

    作者回复: 看怎么理解,如果你理解能操作UI的线程就是UI线程,那UI线程确实不一定是主线程

    2019-12-10
    1
  • 菜头
    如果是获取系统相册直接获取 图片对象 Dart 支持各个平台的 image 对象类型吗

    作者回复: 这种建议只在原生实现界面,flutter接受最后选择的图片地址

    2019-11-03
  • 辉哥
    问一下,Flutter和原生应用应该不处于同一个进程吧

    作者回复: 不特殊处理的话,是一个进程

    2019-09-24
  • 江宁彭于晏
    // 声明 MethodChannel const platform = MethodChannel('samples.chenhang/utils'); // 处理按钮点击 handleButtonClick(Map paramDic) async{ int result; // 异常捕获 try { // 异步等待方法通道的调用结果,Map 中插入appid和包名,跳转链接等信息 result = await platform.invokeMethod('openAppMarket', [paramDic]); } catch (e) { result = -1; } print("Result:$result"); }

    作者回复: 这个接口的易用性貌似不太合理啊,调用方和原生代码宿主对于参数的处理都比较别扭

    2019-09-11
  • 小水滴
    iOS系统创建多份FlutterViewController会有什么问题吗

    作者回复: 每启动一个 FlutterVC实例,就会创建一套新的渲染机制,即 Flutter Engine,以及底层的 Isolate。这些实例之间的内存是不互相共享的,系统资源消耗比较大

    2019-08-30
  • ptlCoder
    methodChannelWithName:@"samples.chenhang/utils" 这个通道名称有什么要求嘛?还是说见名知意就好? 另外,如果flutter很多地方都用到了原生系统方法,岂不是在iOS或安卓flutter入口那做很多个判断?

    作者回复: 1.没要求,主要Dart层与原生宿主层保持一致就可以; 2.对

    2019-08-29
  • 许童童
    dart层通过platform.invokeMethod 第二个参数传入动态参数 native层可以通过call.argument拿到参数

    作者回复: 赞

    2019-08-27
  • dart层: platform.invokeMethod('openAppStore', {"appId": "com.tencent.mm"}); native层: String appId = call.argument("appId"); try { Uri uri = Uri.parse("market://details?id=" + appId); Intent intent = new Intent(Intent.ACTION_VIEW, uri); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } catch (Exception e) { result.error("UNAVAILABLE", "没有安装应用市场", null); }

    作者回复: 赞

    2019-08-27
收起评论
显示
设置
留言
17
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部