flutter插件三步走
1.flutter插件的新建及主要文件夹介绍
2.flutter 插件常用通道MethodChannel方法实现两端数据通信
打开android studio 选择 file->new->new flutter project点击新建,选择你的flutter SDK 路径
点击next进入新建界面
填写项目相关信息点击finish创建项目,项目我们只需要重点关注下图四个文件夹即可
如上图所示,我们所需要修改的文件就是如上图中标记的图片,在新建的demo中会自带一个获取版本号的插件方法,接下来我们就根据此方法来讲解插件的一整套流程,首先我们看flutter端的方法梳理
如上图,我们打开测试demo文件夹,进入到main.dart文件下,代码很简单,先获取untitled2的实例,通过实例调用它的getPlatformVersion方法,获取版本号,那么untitled2类中定义了什么呢,
如上图所示,该文件导入untitled2_platform_interface 文件,通过Untitled2Platform.instance.getPlatformVersion(),获取版本号,这时我们需要关注instance,因为我们获取版本号的方法是通过instance对应的实例来获取的,那么instance是什么?带着这个疑问我们继续点击getPlatformVersion()方法会进入到untitled2_platform_interface.dart文件中,
我们发现该文件中导入了untitled2_method_channel文件,而我们关注的instance所对应的实例为MethodChannelUntitled2类所生成的实例,看到这里我们可以知道,我们具体获取版本号的方法是被定义在MethodChannelUntitled2中,此类还定义了getPlatformVersion()方法的异常报错,而此类在untitled2_method_channel文件中,我们进入MethodChannelUntitled2中看到如下图所示
进入后我们发现该文件导入了untitled2_platform_interface文件,而MethodChannelUntitled2是继承自untitled2_platform_interface文件的Untitled2Platform类,在此类中我们看到了,flutter插件用来通讯的MethodChannel方法,到此,我们可以基本梳理一下,这几个文件的作用了。
其实整个交互的主要文件是untitled2_method_channel文件,demo在开发时做了简单的封装,untitled2文件为暴露给外部调用的文件,untitled2_platform_interface文件中定义插件的方法,并暴露具体实现类对象给untitled2,untitled2_method_channel文件则是具体的插件方法的实现。当然,我们也可以在一个文件中实现所有的。
文章到这里,我们基本理清了flutter端demo代码的逻辑。下面我们再来看一下android 端及IOS端的代码
如上图所示,我们打开android端代码,点击上图标记处,以android项目的形式打开,打开后需要等一下,因为需要下载一些相对应的代码
下载完成前
下载完成后:
下载后如果出现报错如下图,这是因为下载出问题
可以在demo文件夹下的build.gradle文件中截图位置增加下面这行代码
maven { url "https://storage.googleapis.com/download.flutter.io" }
重新build即可 。
接下来,我们看一下android端的代码:
android端代码也很少,onAttachedToEngine()主要是用来做一些初始化工作,例如上图中的通过MethodChannel建立通道,onMethodCall 对具体方法的响应,通过call.method来判断具体的功能即然是通道,通过result.success来返回执行结果。那么flutter应该也有相应的代码,我们回到flutter端,如下图
我们看,flutter端也是通过MethodChannel来建立通道,通过invokeMethod来确认方法。
IOS同理:
了解了它的流程,我们就可以仿照流程实现我们自己的通道插件
三部曲:1根据需求,首先定义flutter插件方法;2,android及IOS端实现插件方法;3,flutter项目进行调用
具体代码实现如下:
1.untitled2_platform_interfac文件定义需要实现的方法及参数类型
Future<String?> getStringForIOS(int string) {
throw UnimplementedError('getStringForIOS() has not been implemented.');
}
Future<String?> printerAPP(Map<String,dynamic> string) {
throw UnimplementedError('printer() has not been implemented.');
}
2.untitled2_method_channel定义方法名称
@override
Future<String?> getStringForIOS(int string) async {
final version = await methodChannel.invokeMethod<String>('getStringForIOS',string);
return version;
}
@override
Future<String?> printerAPP(Map<String,dynamic> string) async {
final version = await methodChannel.invokeMethod<String>('printer',string);
return version;
}
android端及IOS端实现具体方法
//android端代码
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${Build.VERSION.RELEASE}")
} else if (call.method =="printer"){
var string = call.arguments.toString();
var zqPrinterBean = JsonUtils().fromJson<ZQPrinterBean>(string)
var resultObj = ZQ420Printer(context).zeroSymbolBill(zqPrinterBean,0)
Config.Config(context).macAddress = "AC:3F:A4:4C:0D:ED"
result.success(resultObj.message)
}else{
result.notImplemented()
}
}
//IOS端代码
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
if call.method == "getPlatformVersion"{
result("iOS " + UIDevice.current.systemVersion)
}else if call.method == "getStringForIOS"{
var ss = call.arguments as! Int
var restltA = ss+100
print(ss)
// var sint = Int(ss)+100
result("传值加100=====\(restltA)")
}
}
IOS 端可以使用Xcode编译器开发,打开路径example->ios选择,右键点击选择flutter->open ios module in Xcode,进入Xcode编译器,注意,在进入前需要先运行出IOS程序,否则可能出现无法选择的情况,进入Xcode,选择如下图路径中进行编写即可
接下来可以进入demo中调用
//在demo中调用
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> getStringForIOS(Map<String,dynamic> str) async {
String string;
// Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null.
try {
string =
await _flutterplugindemo2Plugin.printerAPP(str) ?? 'Unknown String';
var s = _flutterplugindemo2Plugin.getStringForIOS(1);
} on PlatformException {
string = 'Failed to getStringForIOS';
}
// 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(() {
_iosString = string;
});
}
至此,通过MethodChannel方法进行插件化开发完成了