前言

上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信。

并且也看到了 Flutter 内部 EventChannel 源码也是对 MethodChannel 的封装。

因此这篇我们来说下如何通过 MethodChannel 实现 Android -> Flutter 的通信。

至于 Flutter -> Android 的通信,没看过的小伙伴建议看下之前的文章 Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

既然我们之前写过 Flutter -> Android 的 MethodChannel,那么我们现在要写 Android -> Flutter 的 MethodChannel,可以仿照一下原先的写法。

步骤如下:

第一步:Flutter UI 修改

我们的代码在上一篇的基础上做修改,在列上面增加一个文本用于确认收到了 Android 的请求。

String _arguments = 'unknown';
Text(_arguments),

第二步:在 Android 端写 invokeMethod 引用 Flutter 方法

methodChannel.invokeMethod("getContent", "arguments", new MethodChannel.Result() {
@Override
public void success(@Nullable Object o) {
Log.e(TAG, "success="+o);
} @Override
public void error(String s, @Nullable String s1, @Nullable Object o) {
Log.e(TAG, "error="+s);
} @Override
public void notImplemented() {
Log.e(TAG, "notImplemented");
}
});

参数说明:

第一个为方法名。用于 Flutter 区分 Android 的不同请求。

第二个为参数值。用于 Android 需要给 Flutter 传递的额外数据。

第三个为 Android -> Flutter 请求的结果回调。

回调有三种情况:

1)调用成功

2)调用失败

3)Flutter 未实现对应方法

第三步:在 Flutter 调用对应 MethodChannel 的 setMethodCallHandler

methodChannel.setMethodCallHandler((MethodCall call){
if (call?.method == 'getContent') {
setState(() {
_arguments = call?.arguments ?? '';
});
}
});

看到这里的 MethodCall 你应该很熟悉了,通过 call.method 可以知道 Android 要获取的方法名,通过 call.arguments 可以拿到 Android 传递过来的数据。

这里的 getContent 对应 Android 的 invokeMethod。

为了确认我们获取到了,我们将 Android 传递过来的参数显示出来。

第四步:运行

可以看到效果如下:

初始显示 unknown

点击后显示原生传过来的内容

同时控制台显示打印信息如下:

success=null

我们发现 Android 确实回调成功了,但是另一个问题随之而来,Flutter 如何将内容回调给 Android?

解决问题一时爽,一直解决问题一直爽。

也是很简单的,就是我们写一个异步方法将信息带回去即可。

在 setState 方法后面添加下面代码:

return returnToRaw();

具体方法实现如下:

Future<String> returnToRaw() async {
return 'received your message';
}

这个时候再运行点击按钮会发现控制台打印如下信息:

success=received your message

可以看到成功收到返回值了。

这里演示返回的是字符串,因此异步方法返回类型是 Future 。如果你要返回其他类型,可以自行修改。

如果希望回调 notImplemented,不要在 Flutter 调用 MethodChannel 的 setMethodCallHandler 或者 setMethodCallHandler 的参数设置为 null 即可。

    //方法一
// methodChannel.setMethodCallHandler((MethodCall call){
// if (call?.method == 'getContent') {
// setState(() {
// _arguments = call?.arguments ?? '';
// });
// return returnToRaw();
// }
// });
//方法二
methodChannel.setMethodCallHandler(null);

如果希望回调 error,修改 returnToRaw 方法即可。如下:

Future<String> returnToRaw() async {
throw PlatformException(code: 'error code');
}

这里通过抛出 PlatformException 并将错误信息带回去给 Android。

一般错误信息除非是手动需要抛,否则源码会帮我们处理的。

这里是为了演示所以手动抛出异常。

好了,至此 MethodChannel Android-> Flutter 我们也实现了。

其实不管是 Android -> Flutter 还是 Flutter-> Android,都是平台相关代码。

因此可以直接到 platform_channel.dart 里面看看源码。

除了 EventChannel、MethodChannel,还有 BasicMessageChannel 和 OptionalMethodChannel,这些就交给小伙伴们自己去研究了。

后记

这边分享一下研究 MethodChannel 实现 Android -> Flutter 的过程遇到的坑。

希望不止是授大家以鱼,更是授大家以渔

坑1:一开始将原生 MethodChannel 写到外面,导致 Flutter 没收到请求

因为 Flutter 是在 initState 里面去 setMethodCallHandler 的,而 debug 模式下可能 Flutter 还没加载完成,这个时候发送消息,Flutter 就可能没收到。

后面改成点击之后 Flutter -> Android,Android 再发给 Flutter。

这个问题是异步的原因导致的。

明确之后通过正确的方式就可以收到请求了。

坑2:Flutter 收到之后,如何回调回消息呢?

首先点击进入 setMethodCallHandler 源码,如下:

void setMethodCallHandler(Future<dynamic> handler(MethodCall call)) {
BinaryMessages.setMessageHandler(
name,
handler == null ? null : (ByteData message) => _handleAsMethodCall(message, handler),
);
}

再深入 _handleAsMethodCall,如下:

Future<ByteData> _handleAsMethodCall(ByteData message, Future<dynamic> handler(MethodCall call)) async {
final MethodCall call = codec.decodeMethodCall(message);
try {
return codec.encodeSuccessEnvelope(await handler(call));
} on PlatformException catch (e) {
return codec.encodeErrorEnvelope(
code: e.code,
message: e.message,
details: e.details,
);
} on MissingPluginException {
return null;
} catch (e) {
return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null);
}
}

到这里就比较明朗了。

可以看到错误基本不用我们处理,也没有太多可介入空间。

但是成功回调,这里核心语句是

await handler(call)

因此我们上面通过一个异步方法返回字符串给原生。

由于笔者之前对 Future 不是很熟,因此为了解决这个问题,看了 dart 源码

Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)的更多相关文章

  1. Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)

    前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...

  2. Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

    背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...

  3. Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

    前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...

  4. Flutter 即学即用系列博客总结篇

    前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...

  5. Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

    前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...

  6. Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  7. Flutter 即学即用系列博客——06 超实用 Widget 集锦

    本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...

  8. Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明

    前言 上一篇文章我们搭建好了 Flutter 的开发环境. Flutter 即学即用--01 环境搭建 这一篇我们通过 Flutter 的一个 Demo 来了解下 Flutter. 开发系统:MAC ...

  9. Flutter 即学即用系列博客——10 混淆

    前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...

随机推荐

  1. 【爆料】-《悉尼大学毕业证书》USYD一模一样原件

    ☞悉尼大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归&a ...

  2. Docker系列之swarm集群搭建

    学习Docker很久了,今天分享一下Docker的swarm集群的搭建过程很简单 首先第一步是 每台机器上面都要安装docker 本人使用的是centos7操作系统,使用3太虚拟机,3太虚拟机必须网络 ...

  3. Windows上安装配置SSH教程(1)——知识点汇总

    1.是什么SSH? 维基百科:https://zh.wikipedia.org/wiki/Secure_Shell 其他博客:http://www.ruanyifeng.com/blog/2011/1 ...

  4. java基础(六)-----String性质深入解析

    本文将讲解String的几个性质. 一.String的不可变性 对于初学者来说,很容易误认为String对象是可以改变的,特别是+链接时,对象似乎真的改变了.然而,String对象一经创建就不可以修改 ...

  5. js十大排序算法

    排序算法说明: (1)对于评述算法优劣术语的说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面:不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面: 内排序:所有排 ...

  6. Redux的中间件原理分析

    redux的中间件对于使用过redux的各位都不会感到陌生,通过应用上我们需要的所有要应用在redux流程上的中间件,我们可以加强dispatch的功能.最近也有一些初学者同时和实习生在询问中间件有关 ...

  7. Wmyskxz文章目录导航附Java精品学习资料

    前言:这段时间一直在准备校招的东西,所以一晃眼都好长时间没更新了,这段时间准备的稍微好那么一点点,还是觉得准备归准备,该有的学习节奏还是要有..趁着复习的空隙来整理整理自己写过的文章吧..好多加了微信 ...

  8. 【极简版】SpringBoot+SpringData JPA 管理系统

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在上一篇中已经讲解了如何从零搭建一个SpringBo ...

  9. spark集群搭建整理之解决亿级人群标签问题

    最近在做一个人群标签的项目,也就是根据客户的一些交易行为自动给客户打标签,而这些标签更有利于我们做商品推荐,目前打上标签的数据已达5亿+, 用户量大概1亿+,项目需求就是根据各种组合条件寻找标签和人群 ...

  10. javascript入门篇(三)

    字符串属性和方法 原始值字符串,如'liang', 没有属性和方法(因为他们不是对象). 原始值可以使用 JavaScript 的属性和方法,因为 JavaScript 在执行方法和属性时可以把原始值 ...