Flutter开发进阶:Channel
2022-03-07 本文已影响0人
__Null
1.初始化路由传值
//ios
let vc = FlutterViewController()
vc.setInitialRoute("openCompany")//设置为one
self.navigatonController?.present(vc, animated:true)
//flutter
void main() => runApp(MyApp(pageIndex:window.defaultRouteName));
class MyApp extends StatelessWidget {
final String pageIndex;//接收到openCompany
const MyApp({Key? key, required this.pageIndex}) : super(key:key);
Widget build(BuildContext context){
//根据pageIndex去加载页面
return ...
}
}
- 是单向的,只能App给flutter传递,导致页面不能关闭。
2.MethodChannel通信
//ios
let engine = FlutterEngine(name: "app")
var flutter : FlutterViewController? = nil
override func viewDidLoad(){
engine.run()
self.flutter = FlutterViewController(engine: self.engine, nibName: nil, bundle: nil)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let __flutter = self.flutter {
let channel = FlutterMethodChannel(name: "explorer", binaryMessenger: __flutter.binaryMessenger)
self.present(__flutter, animated: true, completion: nil)
channel.setMethodCallHandler { method, result in
if(method.method == "exit"){
NX.print(method.method)
}
}
channel.invokeMethod("openCompany", arguments:nil);
}
}
//flutter
void main() => runApp(MyApp());
class MyApp extends StatefullWidget {
const MyApp({Key? key});
MyAppState createState() => MyAppState()
}
class MyAppState extends State<MyApp> {
const channel = MethodChannel("explorer");
String pageIndex;//接收到openCompany
void initState(){
channel.setMethodCallHandler((call){
pageIndex = call.method;//openCompany
setState({});
});
}
Widget build(BuildContext context){
//根据pageIndex去加载页面
//响应事件
{
channel.invokeMapMethod("exit", {});
}
return ...
}
}
- FlutterEngine模式下setInitialRoute失效
3.Channel
1.FlutterMethodChannel
传递方法的,方法调用(案例如上)
2.FlutterBasicMessageChannel
持续通信,收到消息后还可以恢复
//ios
let channel = FlutterBasicMessageChannel(name: "explorer", binaryMessenger: __flutter.binaryMessenger)
channel.setMessageHandler { value, reply in
//收到来自flutter的消息
}
channel.sendMessage("----")//发送给flutter的消息
//flutter
BasicMessageChannel channel = BasicMessageChannel("explor", StandardmessageCodec());
channel.setMessageHandler((message){
//来自App的消息
});
channel.send("-----")//发给App的消息
3.EventChannel
数据流
4.Flutter引擎源码
https://blog.csdn.net/dongzhong1990/article/details/105678124
源码主要分为两部分:
Flutter官方源码下载路径:
engine: https://github.com/flutter/engine
flutter framework: https://github.com/flutter/flutter
- Engine,是可供Flutter宿主应用提供的一个可移植运行时。Engine实现了Flutter的核心库,包括动画、图形、文件、网络I/O、访问支持、插件架构和Dart的运行时、编译工具链;
- Flutter Framework,大部分的Flutter开发者主要通过Flutter Framework交互。Framework提供了一个现代的、可交互的框架,以及一个丰富的平台、布局、基础部件的集合。
1.channel通信原理
1.1.MethodChannel通信
let channel = FlutterMethodChannel(name:"explorer", binaryMessenger: self.flutterViewController.binaryMessenger)
初始化方法:将如下三个信息保存起来
- name:channel名称
- binaryMessenger:消息管理器
- codec:解码器(上层传空时下层会自动调用单例)
channel.setMethodCallHandler { method, result in
if(method.method == "exit"){
}
}
设置消息回调:判断handler是否为空,来进行历史数据的清空和重新赋值。
- handler:最终毁掉到上层的一个句柄
- 内部会自己定义一个messageHandler,用来接收最下层的回调,并且可以把消息抛到最上层。
- 内部会将新定义的channel.name和messageHandler用key-value的形式保存起来。
channel.invokeMethod("openDetail", arguments: nil, result: {})
- 通过channel.name找到dart部分的消息回调,然后执行handler big你就爱哪个数据传递过去
2.解码器
三种channel有2种解码器,解码器实际上是一种数据转换协议,iOS、Android、dart三端通用。
2.1.FlutterMessageCodec
@protocol FlutterMessageCodec
+ (instancetype)sharedInstance;
- (NSData * _Nullable)encode:(id _Nullable)message;
- (id _Nullable)decode:(NSData * _Nullable)message;
@end
2.2FlutterMethodCodec
服务Methodchannel、EventChannel
@protocol FlutterMethodCodec
+ (instancetype)sharedInstance;
- (NSData *)encodeMethodCall:(FlutterMethodCall *)methodCall;
- (NSData *)decodeMethodCall:(NSData *)methodCall;
- (NSData *)encodeSuccessEnvelope:(id _Nullable)result;
- (NSData *)encodeErrorEnvelope:(FlutterError *)error;
- (id _Nullanle)decodeEnvelope:(NSData *)envelope;
@end
2.3 FlutterStandardReaderWriter
- FlutterStandardReader
- (nullable id)readValue {
//
[self readValueOfType:[self readByte]]
}
- (nullable id)readValueOfType:(UInt8)type{
}
- FlutterStandardWriter
- (void)writeValue:(id)value {
//判断类型
//写入标志位(数据类型)+数据本身
[- writeByte:]
[- writeBytes:- length:-]
}