为了解决调用原生系统底层能力以及相关代码库复用问题,Flutter 为开发者提供了一个轻量级的解决方案,即逻辑层的方法通道(Method Channel)机制。基于方法通道,我们可以将原生代码所拥有的能力,以接口形式暴露给 Dart,从而实现 Dart 代码与原生代码的交互,就像调用了一个普通的 Dart API 一样。
方法通道
一次典型的方法调用过程类似网络调用,由作为客户端的 Flutter,通过方法通道向作为服务端的原生代码宿主发送方法调用请求,原生代码宿主在监听到方法调用的消息后,调用平台相关的 API 来处理 Flutter 发起的请求,最后将处理完毕的结果通过方法通道回发至 Flutter。
下面来实现一次方法调用请求
首先,我们需要确定一个唯一的字符串标识符,来构造一个命名通道;然后,在这个通道之上,Flutter 通过指定方法名“ testChannel”来发起一次方法调用请求。
可以看到,这和我们平时调用一个 Dart 对象的方法完全一样。因为方法调用过程是异步的,所以我们需要使用非阻塞(或者注册回调)来等待原生代码给予响应。
需要注意的是,与网络调用类似,方法调用请求有可能会失败,因此我们需要把发起方法调用请求的语句用 try-catch 包装起来。
class _HomeMainPageState extends State<HomeMainPage> with AutomaticKeepAliveClientMixin {
/// 保持状态
@override
bool get wantKeepAlive => true;
String testStr;
static const platform = MethodChannel("ESHOPCHANNEL");
@override
void initState() {
super.initState();
_testChannel();
}
_testChannel() async {
var str;
try {
str = await platform.invokeMethod<String>('testChannel');
setState(() {
testStr = str;
});
} catch (e) {
debugPrint(e.toString());
}
}
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: Center(child: Text(testStr ?? ""),),
);
}
}
iOS端处理
在入口方法内部创建一个FlutterMethodChannel,并添加一个处理方法。 确保与在Flutter客户端使用的通道名称相同。
// AppDelegate.swift
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
if let controller: FlutterViewController = window?.rootViewController as? FlutterViewController,
let binaryMessager = controller as? FlutterBinaryMessenger {
let batteryChannel = FlutterMethodChannel.init(name: channelName, binaryMessenger: binaryMessager)
batteryChannel.setMethodCallHandler(MethodChannelManager.manager.methodCallHandler(call:result:))
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
******************
// MethodChannelManager.swift
let channelName = "ESHOPCHANNEL"
class MethodChannelManager {
// 单例
static let manager = MethodChannelManager()
private init(){}
func methodCallHandler(call: FlutterMethodCall, result: FlutterResult) {
guard let type = MethodChannelType(rawValue: call.method) else {
result(FlutterMethodNotImplemented)
return
}
switch type {
case .test:
testChannel(result: result)
}
}
// test
private func testChannel(result: FlutterResult) {
result("test")
}
}
enum MethodChannelType: String {
case test = "testChannel"
}
网友评论