flutter插件基础之调用MethodChannel的基本使用(二)

本篇,我们接着对flutter插件中MethodChannel的使用进行研究。。。

封面配图.jpg

开始~~

二.MethodChannel的使用

1.官方案例介绍

1.1.运行官方案例后发生了什么

接着上次的流程来说,当我们尝试在安卓studio上把项目运行起来后,屏幕上显示如下所示:


flutterdemo示例.jpeg

即通过原生安卓的方法获取到了安卓的版本号,为安卓10,展示在了flutter项目中。

进一步,按照我们上篇的分析步骤分析如下代码为examle/main.dart中的部分代码如下

@override

**void** initState() {

 **super**.initState();

 initPlatformState();

}

*// Platform messages are asynchronous, so we initialize in an async method.*

Future<**void**> initPlatformState() **async** {

 String platformVersion;

 *// Platform messages may fail, so we use a try/catch PlatformException.*

 *// We also handle the message potentially returning null.*

**try** {

 platformVersion =

 **await** FlutterPluginDemo2.*platformVersion* ?? **'Unknown platform version'**;

 } **on** PlatformException {

 platformVersion = **'Failed to get platform version.'**;

 }

 *// If the widget was removed from the tree while the asynchronous platform*

 *// message was in flight, we want to discard the reply rather than calling*

 *// setState to update our non-existent appearance.*

**if** (!**mounted**) **return**;

 setState(() {

 **_platformVersion** = platformVersion;

 });

}

即通过调用FlutterPluginDemo2.platformVersion 方法获取原生版本号,那么在FlutterPluginDemo2类中又是如何实现的呢,如下所示为lib/flutter_plugin_demo2.dart中的代码

**class** FlutterPluginDemo2 {

 **static const** MethodChannel *_channel* = MethodChannel(**'flutter_plugin_demo2'**);

 **static** Future<String?> **get** *platformVersion* **async** {

 **final** String? version = **await** *_channel*.invokeMethod(**'getPlatformVersion'**);

 **return** version;

 }

}

它的调用原理是如何呢?

可以看到通过建立一个MethodChannel通道,给这个通道设置一个key值为flutter_plugin_demo2,之后再给要调用的方法设置一个key只为getPlatformVersion。

如此在插件端,如以安卓为例如下的
android/src/main/java/com/example/flutter_plugin_demo2 路径下的FlutterPluginDemo2Plugin.java类 中如下代码片段中


@Override

**public void** onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {

 **channel** = **new** MethodChannel(flutterPluginBinding.getBinaryMessenger(), **"flutter_plugin_demo2"**);

 **channel**.setMethodCallHandler(**this**);

}

@Override

**public void** onMethodCall(@NonNull MethodCall call, @NonNull Result result) {

 **if** (call.method.equals(**"getPlatformVersion"**)) {

 result.success(**"Android "** + android.os.Build.VERSION.RELEASE);

 } **else** {

 result.notImplemented();

 }

}

发现了没,这里也有一个flutter_plugin_demo2,也有一个 getPlatformVersion的key,如此我们就清晰了Method Channel的机制,可以这样理解为

通过flutter端设置一个固定的字符串key同安卓原生端的key保持一致,可以使flutter插件和原生建立起基础通信,而后根据调用方法时同样传递一个key值(如官方示例中的getPlatformVersion)和原生的onMethodCall方法中的call.method对应的值保持一致即可成功调用到安卓端的接口,而后通过

result.success 把对应获取到的原生信息回传给flutter端,从而让flutter拿来进行展示和进一步数据处理工作

1.2.尝试按照官方案例写一个自己的插件(以安卓为例)

首先打开原生工程代码的方法如下所示:

对于安卓端打开方法为:

安卓插件打开.png

对于iOS端打开方法如下:

iOS插件打开1.png

需要注意的是,在iOS中若需要先进入example/ios 目录下执行 flutter run 命令进行Pods的构建才会出现如上的iOS端插件构建代码,否则,是无法进入iOS端原生代码的。

iOS插件打开2.png

运行项目后展示内容为自己写的一个当用户点击flutter调用安卓原生按钮后,安卓回调数据为 Android: 获取安卓数据成功的示例,即可简称为调——设——回三部曲

第1步—在flutter代码中调用

在flutter示例代码example/lib/main.dart中代码如下所示:

Future<**void**> updateAndroidInfoData() **async** {

 String originalStr;

 **try** {

 originalStr =

 **await** FlutterPluginDemo2.*originalAllData* ?? **"Unknow Not Back"**;

 } **on** PlatformException {

 originalStr = **"Failed Not Back"**;

 }

 **if** (!**mounted**) **return**;

 setState(() {

 **_originalStr** = originalStr;

 });

}

执行该方法后

第2步—在flutter插件代码中设置key

在lib/flutter_plugin_demo2.dart中加入调用安卓的代码如下


**static** Future<String?> **get** *originalAllData* **async** {

 **final** String? originalStr = **await** *_channel*.invokeMethod(**'originalAllData'**);

 **return** originalStr;

}

设置调用的key为 originalAllData

第3步—在原生(如下为安卓)代码中回传原生数据给flutter

3.同时在FlutterPluginDemo2Plugin.java类中增加call.method.equals("originalAllData”)内容如下,

**else if** (call.method.equals(**"originalAllData"**)) {

 result.success(**"Android: "** + **"获取安卓数据成功"**);

}

如此,经历此三步曲后,就可以实现一个最简单的flutter调用原生安卓,安卓同步回传数据给flutter的基础通信架构的功能实现。

2.传值方法汇总

接下来,我们来聊聊关于如何借助MethodChannel来实现把值传给原生,原生经过加工处理后返回给flutter,从而实现flutter调用原生,原生加工后回调给flutter的操作。

来吧,展示~~

2.1.简单传值——flutter调用原生

聊传值之前,先来说说原生接收值的原理,即为flutter和原生直接是通过一个MethodCall的call对象传值的原理,即当flutter中按照官方文档的要求传值给原生后,原生是通过call.arguments来获取到传递的值,从而对值进行加工后返回的操作。

如下所示为flutter端传递一个动态的数字给原生端,原生端实现的是一个超级简易的计算器,即如果是iOS平台,给flutter端传递的数字 翻10倍后返回展示,如果是安卓平台,则把传递的数字返回它的平方。

接下来贴代码进行说明:

1.flutter端的代码示例

在example/lib/more_Params_page.dart(即flutter端使用插件的地方)文件中执行以下方法后,把对应的type,即用户输入的内容传递给中间插件FlutterPluginDemo2类。


Future<**void**> sendParamsToOriginal() **async** {

 String originalStr;

 **try** {

 originalStr = **await** FlutterPluginDemo2.*sendParamsToOriginal*(**type**!,**"传给原生"**) ?? **"0"**;

 } **on** PlatformException {

 originalStr = **"0"**;

 }

 **if** (!**mounted**) **return**;

 setState(() {

 **_paramStr** = originalStr;

 });

}

2.中间插件的代码示例

如下所示为

**static** Future<String?> *sendParamsToOriginal*(int key,String value) **async** {

 Map params = {

 **"key"**:key,

 **"value"**:value,

 };

 **final** String? count = **await** *_channel*.invokeMethod(**'sendParamsToOriginal'**,params);

 **return** count;

}

lib/flutter_plugin_demo2.dart中提前写好的插件端调用原生端的代码示例,并传递flutter端的代码至插件端,插件端包装完成后向下继续传递原生。

3.原生端的代码示例

3.1.安卓端

同上所示,安卓端在FlutterPluginDemo2Plugin.java类中的onMethodCall方法中设置同中间插件一致的key,如demo所示的sendParamsToOriginal,根据

MethodCall对象的原理方式获取到flutter端传递过来的参数为call.argument,之后取出传递的值,然后平方相乘后返回给插件,之最上层的flutter端进行展示。

**else if** (call.method.equals(**"sendParamsToOriginal"**)) {

 **int** key = call.argument(**"key"**);

 result.success(**"Android端 - 计算乘积为 "** + key * key);

}

3.2.iOS端

同理,iOS端代码示例在FlutterPluginDemo2Plugin.m类中的handleMethodCall

方法中部分代码如下所示

**else if** ([**@"sendParamsToOriginal"** isEqualToString:call.method]) {

 NSDictionary *params = call.arguments;

 NSLog(**@"params = "**,params);

 **int** key = [params[**@"key"**] intValue];

 result([**@"iOS端 - 计算翻10倍后为:"** stringByAppendingString: [NSString stringWithFormat:**@"%d"**,key * 10]]);

}

最后,由于flutter和原生端交互时难免涉及到数据类型的转换问题,特别是int类型,这里一并展示转换如下所示:

java转flutter.png
oc转flutter.png

另外本篇的demo连接一并附上如下:Flutter插件demo

综上,关于MethodChannel的基础使用,本篇从官方案例获取系统版本号的分析,到模仿官方案例加入自己调用不同原生返回内容,以及通过简单传递参数给原生加工后返回给flutter的案例来整体对MethodChannel在插件编写中的使用进行了全面的描述;

但尴尬的问题是,本篇中实现的仅仅是flutter端和原生端保持同步状态,实际开发中如声音音量的变化是不可能由flutter端调用安卓然后安卓给回应的,而更可能是flutter端在监听原生,原生端音量发生变化后通知到flutter端,然后去做对应的业务处理,那么就留到下一篇聊这个问题的解决方案。

flutter插件基础之基本介绍和工程目录介绍(一)

本篇完~~

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

推荐阅读更多精彩内容