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插件基础之基本介绍和工程目录介绍(一)

本篇完~~

推荐阅读更多精彩内容