引入 Flutter 实战开发入门

本文目标

  1. 将 Flutter 引入到日常的开发;
  2. 熟悉引入 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* _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

你可能感兴趣的:(引入 Flutter 实战开发入门)