前言
混合开发(Hybird模式)是当下大部分APP开发的主流方式。通常我们将APP内变化比较频繁,业务比较轻,且对性能要求不是特别高的的功能,通过一些非原生的手段来实现,比如最简单的嵌套一个WebView,然后通过JSBridge的方式来实现双向通行,从而实现页面的动态更新;同样的在React Native,Weex,和Flutter中都提供的混合开发的能力。今天我们就看下Flutter如何与原生混合开发(这里主要以iOS开发为例);
这里需要注意的是如果需要支持混合开发,整个Flutter项目需要创建为Module,然后将Module引入iOS/Android项目中,iOS通过cocoaPods来引入并加载。
创建Flutter-Module项目
项目结构对比
我发现的唯一区别就是原来的
android
和ios
文件夹变成了隐藏文件。而且Module项目是可以独立运行的。
创建一个iOS项目
通常在Flutter混合开发项目中,我们的iOS或者Android项目会创建在Module的同级目录下(实际上就是为了引用个时候方便,其实我们完全可以将Module创建在任意位置,只是在项目中引用时路径太恶心罢了)。
- 通过
pod
引入引入flutter_module,配置Podfile
:
# Uncomment the next line to define a global platform for your project
flutter_application_path = '../flutter_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
platform :ios, '9.0'
use_frameworks!
target 'Flutter_iOS' do
install_all_flutter_pods(flutter_application_path)
end
执行pod install
,此时我们的原生项目就引入了整个flutter_module
;
- 原生调起Flutter模块
#import "ViewController.h"
#import
@interface ViewController ()
@property (nonatomic,strong) FlutterViewController *flutterVC;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.flutterVC = [[FlutterViewController alloc]init];
}
- (IBAction)toFlutterModule:(UIButton *)sender {
[self presentViewController:self.flutterVC animated:YES completion:nil];
}
@end
这里值得注意的是flutterVC
的初始化我没有放在点击事件内部,而是放在viewDidLoad
中,FlutterViewController
是一个特殊的视图控制器,并不像我们平常使用的UIViewController
,在dismiss
或者pop
后会被释放,它不会被释放而且它被创建后的生命周期跟AppDelegate是一致的。
在纯flutter项目中,FlutterViewController
通常被指定为UIApplication.keyWindow.rootViewController
。
通信
这里主要用到的是MethodChannel
MethodChannel
中两个核心的方法:
-
setMethodCallHandler:
注册监听,处理收到的消息 -
invokeMethod:
发送消息
- Flutter
class _HomePageState extends State {
//创建通道,设置通道标识
final MethodChannel _msgChannel = MethodChannel('msg_channel');
@override
void initState() {
// TODO: implement initState
super.initState();
//添加监听,接受来自native的消息
_msgChannel.setMethodCallHandler((MethodCall call){
print('收到iOS的消息=>${call.method}\n${call.arguments}');
return null;
});
}
GestureDetector(
onTap: (){
print('onTap.....');
//向native发送消息
_msgChannel.invokeMethod('disMissVC',{'name':'zezefamily','age':'3','from':'Shannxi of China'});
},
child: Text('返回上一页'),
)
- Native
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.flutterVC = [[FlutterViewController alloc]init];
//创建通道,并绑定通道标识
self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"msg_channel" binaryMessenger:self.flutterVC];
//添加监听:接收来自Flutter的消息
__weak typeof(self) weakSelf = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
if([call.method isEqualToString:@"disMissVC"]){
[weakSelf dismissVC:call.arguments];
}
}];
}
- (void)dismissVC:(id)arguments
{
NSLog(@"来自Flutter=>%@",arguments);
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)nativeToFlutter:(UIButton *)sender {
//Native=>Flutter
[self.methodChannel invokeMethod:@"msg_channel" arguments:@{@"name":@"我是原生",@"desc":@"我给你发消息了"}];
}
控制台输出:
2020-06-23 15:20:54.568666+0800 Flutter_iOS[64555:1302095] flutter: onTap.....
2020-06-23 15:20:54.569892+0800 Flutter_iOS[64555:1301842] 来自Flutter=>{
age = 3;
from = "Shannxi of China";
name = zezefamily;
}
2020-06-23 15:20:56.594187+0800 Flutter_iOS[64555:1302095] flutter: 收到iOS的消息=>msg_channel
{name: 我是原生, desc: 我给你发消息了}
这样就实现了一个双向的通信能力,非常类似于WebViewJavascriptBridge
;
总结
参考文献:https://flutter.dev/docs/development/add-to-app