本文目标
- 将 Flutter 引入到日常的开发;
- 熟悉引入 Flutter 开发后由开发到交付产品的流程;
一个简单的流程图,来表示一下引入 Flutter 后的开发流程:
三个 channel
通常情况下,在现有工程中接入 Flutter 是大部分开发者的选择,即混编。这既兼顾到了大部分开发者以 Native 开发的现状,又能尝一下螃蟹的味道。基于此,我们来看一下一个比较重要的概念 channel。
在混编过程中避免不了原生与 Flutter 侧的数据传递和方法相互调用,Flutter 提供了三个 channel 专门去解决这个比较重要的问题。
这三个 channel 分别是 MessageChannel,MethodChannel,EventChannel,下面分别看一下。
以 Flutter 与 iOS 混编为例,以源码形式集成 Flutter Module ,执行 pod install 之后会自动生成以下三个 channel 类。
FlutterBasicMessageChannel
作用:用于 Native 与 Flutter 传递数据。下面是该类提供的三个比较重要的方法。
// Native 向 Flutter 侧传递数据
- (void)sendMessage:(id _Nullable)message;
// Native 向 Flutter 侧传递数据,并接收 Flutter 侧的回调
- (void)sendMessage:(id _Nullable)message reply:(FlutterReply _Nullable)callback;
// 注册一个回调,用于接收 Flutter 侧返回的回调
- (void)setMessageHandler:(FlutterMessageHandler _Nullable)handler;
FlutterMethodChannel
作用:用于 Native 与 Flutter 之间方法的相互调用。下页是该类提供的三个比较重要的方法。
// Native 调用 Flutter 侧的方法,并传参
- (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments;
// Native 调用 Flutter 侧的方法,并传参,接收 Flutter 侧返回的回调
- (void)invokeMethod:(NSString*)method
arguments:(id _Nullable)arguments
result:(FlutterResult _Nullable)callback;
// 监听 Flutter 侧的方法回调并做相应处理
- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;
FlutterEventChannel
作用:Native 向 Flutter 侧发送通知。下面是该类发送通知的核心方法。
// Native 向 Flutter 侧发送通知,Flutter 侧接收到通知后可以执行相应的操作
- (void)setStreamHandler:(NSObject<FlutterStreamHandler>* _Nullable)handler;
Flutter 与 Android 混编,以源码形式集成 Flutter Module 时,在 build 之后也会生成对应的三个 channel,含义和用法与上面是一样的,就不再列出介绍了。
看完上面三个 channel,是不是感觉这个交互方式有点熟悉。是不是跟 Native 接入 Hybrid 后两者之间的交互方式是类似的的,区别在于 Native 无法向 Hybrid 直接发送通知。你细品!
三种开发模式
三种开发模式是本篇的重点,但这里也不做具体详细的介绍,只介绍其中的关键衔接之处。
Android 与 Flutter 混编
将 Flutter 集成到现有 Android 工程可能参考官方文档,这里主要介绍一下 Android 与 Flutter 衔接的点。
在以 Flutter Module 源码集成后,会生成一个 FlutterView 的类,用于 Android 调起 Flutter 侧的视图。实例化 FlutterView 的一个对象并添加到 Android 端的壳 activity 中,即可以实现 Android 加载 Flutter 侧视图的功能。关键代码如下
FlutterView flutterView = new FlutterView(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout flContainer = findViewById(R.id.layout001);
flContainer.addView(flutterView, lp);
Native 与 Flutter 之间的数据传递,方法调用,通知则以方法相互调用为例说明。
MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor(), 'channel_native');
nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
switch (call.method){
case "openSecondNative":
// 这里执行具体的操作...
result.success("成功打开第二个原生页面");
break;
case "backFirstNative":
// 这里执行具体的操作...
result.success("成功返回第一个原生页面");
break;
case "backAction":
// 这里执行具体的操作...
result.success("成功通过虚拟按键返回第一个原生页面");
break;
default :
result.notImplemented();
break;
}
}
});
iOS 与 Flutter 混编
将 Flutter 集成到现有 iOS 工程可能参考官方文档,这里也主要介绍一下 Android 与 Flutter 衔接的点。
在以 Flutter Module 源码集成后,会生成一个 FlutterViewController 的类,用于 iOS 调起 Flutter 侧的视图。实例化 FlutterViewController 的一个对象并 push 或 present 该对象,即可以实现 iOS 加载 Flutter 侧视图的功能。关键代码如下
let flutterVC = FlutterViewController()
flutterVC.fd_prefersNavigationBarHidden = true
flutterVC.setInitialRoute(paramsJsonStr)
let messageChannel = FlutterMethodChannel(name: "channel_native", binaryMessenger: flutterVC.binaryMessenger)
messageChannel.setMethodCallHandler { [weak self] call, result in
if call.method == "backToMineViewController" {
self?.navigationController?.popViewController(animated: true)
if let tmpArguments = call.arguments as? [AnyHashable: Any] {
let message = tmpArguments["message"] as? String
LoadingManager.showText(message)
}
} else if call.method == "didSelectCell" {
if let tmpArguments = call.arguments as? [AnyHashable: Any] {
self?.handleJump(with: tmpArguments)
}
}
}
flutterVC.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(flutterMessageCenterVC, animated: true)
Native 与 Flutter 之间的数据传递,方法调用,通知也以他们之间的方法相互调用为例说明。看上方代码。
纯 Flutter 开发
对于一个全新的 App 来说,选择纯 Flutter 方式开发或许是一个不错的选择。
一是不用去踩混编的坑,二是越纯粹越简单,包袱也少;
开发完成之后,分别构建各端上的包即可。
一处开发,到处运行,简直不能太爱了!
构建 ipa 或 apk 包
构建包首先要注意的是需要支持哪些架构类型,这关系到你的包发行的广度的问题。下面分别看一下 android 和 iOS 支持的架构类型。
Android 支持的架构
架构类型 | 简介 |
---|---|
arm64-v8a | 第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit |
armeabi | 第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢 |
armeabi-v7a | 第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能(从2010年起) |
x86 | intel 32位,一般用于平板(从2011年起) |
x86_64 | intel 64位,一般用于平板(从2014年起) |
mips | 比较少见(目前市面几乎没有采用这种架构的手机) |
mips64 | 比较少见(目前市面几乎没有采用这种架构的手机) |
设置支持特定架构的包,可以在主工程 app 文件夹下的 build.gradle 添加下面的代码
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "x86", "armeabi"
}
}
iOS 支持的架构
架构类型 | 简介 |
---|---|
armv7s | iPhone5、iPhone5C、iPad4(iPad with Retina Display) |
armv7 | iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)、iPad mini、iPod Touch |
armv6 | iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch(一般不需要去支持) |
arm64e | iphone XS、iphone XS Max、iphoneXR、iphone11、iphone11 Pro |
arm64 | iPhone 5S、iPhone 6、iPhone 6 Plus、iPhone 6S、6S Plus、iPhone 7、7 Plus、iPad (2018)、iPhone 8、iPhone 8 Plus、and iPhone X |
x86_64 | Mac指令集:x86_64是针对x86架构的64位处理器 |
i386 | Mac指令集:i386是针对intel通用微处理器32位处理器 |
可以在 Xcode 中如下图所示的位置设置支持的架构类型
安装
Android apk 包安装
adb install xxx.apk
iOS ipa 包安装
Enterprise 企业包,tf 包
最后
也许一开始引入 Flutter 会面临各种各样的问题。
比如学习成本,新技术的不完备性等风险,但后期带来的收益也是很可观的。
业务是在不断变化的,对高效率的追求却是不变的!Flutter 也许会是一个相对不错的选择!
推荐学习实践:
Flutter、Android混合开发实践:
https://juejin.cn/post/6844904065881604109
Flutter、iOS混合开发实践:
https://juejin.cn/post/6844904087918477320