微店的Flutter混合开发组件化与工程化架构

本文详细介绍了Flutter在混合开发中的组件化与工程化架构,探讨了Flutter与Native的集成原理,包括Android和iOS平台的接入步骤。文章还讨论了Flutter与Native的通信方式,强调了版本一致性管理和自动化构建的重要性。此外,作者提出了组件化架构的最佳实践,将业务组件和基础组件分离,保证代码复用和解耦。最后,文章阐述了工程化架构的两种依赖模式:本地依赖和远程依赖,并介绍了如何无侵入地对Flutter SDK进行BugFix和定制化。
摘要由CSDN通过智能技术生成

A: 2.0.0

四、Flutter链接到Native工程原理

官方提供了一种本地依赖到现有的Native工程方式,具体可看官方wiki:Flutter本地依赖,这种方式太依赖于本地环境和侵入Native工程会影响其它开发同学,且打包平台不支持这种方式的打包,所以肯定得基于这种方式进行优化改造,这个后面再说,先说说Native两端本地依赖的原理

1. Android

在Android中本地依赖方式为:

  1. settings.gradle中注入include_flutter.groovy脚本
  2. 在需要依赖的module中build.gradle添加project(':flutter')依赖

对于Android的本地依赖,主要是由include_flutter.groovyflutter.gradle这两个脚本负责Flutter的本地依赖和产物构建

1. include_flutter.groovy

settings.gradle中注入时,分别绑定了当前执行Gradle的上下文环境与执行include_flutter.groovy脚本,该脚本只做了下面三件事:

  1. include FlutterModule中的.android/Flutter工程
  2. include FlutterModule中的.flutter-plugins文件中包含的Flutter工程路径下的android module
  3. 配置所有工程的build.gradle配置执行阶段都依赖于:flutter工程,也即它最先执行配置阶段

其中.flutter-plugins文件,是根据当前依赖自动生成的,里面包含了当前Flutter工程所依赖(直接依赖和传递依赖)的Flutter子工程与绝对路径的K-V关系,子工程可能是一个Flutter Plugin或者是一个Flutter Package,下面是.flutter-plugins中的一段内容示例: .flutter-plugins:

url_launcher=/Users/Sunzxyong/.pub-cache/hosted/pub.flutter-io.cn/url_launcher-4.0.2/

2. flutter.gradle

该脚本位于Flutter SDK中,内容看起来很长,其实主要做了下面三件事:

  1. 选择符合对应架构的Flutter引擎(flutter.so
  2. 解析上述.flutter-plugins文件,把对应的android module添加到Native工程的依赖中(上述的include其实为这步做准备)
  3. Hook mergeAssets/processResources Task,预先执行FlutterTask,调用flutter命令编译Dart层代码构建出flutter_assets产物,并拷贝到assets目录下

有了上述三步,则直接在Native工程中运行构建即可自动构建Flutter工程中的代码并自动拷贝产物到Native中

2. IOS

在IOS中本地依赖方式为:

  1. 在Podfile中通过eval binding特性注入podhelper.rb脚本,在pod install/update时会执行它
  2. 在IOS构建阶段Build Phases中注入构建时需要执行的xcode_backend.sh脚本

对于IOS的本地依赖,主要是由podhelper.rbxcode_backend.sh这两个脚本负责Flutter的Pod本地依赖和产物构建

1. podhelper.rb

因Podfile是通过ruby语言写的,所以该脚本也是ruby脚本,该脚本在pod install/update时主要做了三件事:

  1. Pod本地依赖Flutter引擎(Flutter.framework)与Flutter插件注册表(FlutterPluginRegistrant)
  2. Pod本地源码依赖.flutter-plugins文件中包含的Flutter工程路径下的ios工程
  3. 在pod install执行完后post_install中,获取当前target工程对象,导入Generated.xcconfig配置,这些配置都为环境变量配置,主要为构建阶段xcode_backend.sh脚本执行做准备

上述事情即可保证Flutter工程以及传递依赖的都通过pod本地依赖进Native工程了,接下来就是构建了

2. xcode_backend.sh

该Shell脚本位于Flutter SDK中,该脚本主要就做了两件事:

  1. 调用flutter命令编译构建出产物(App.framework、flutter_assets)
  2. 把产物(*.framework、flutter_assets)拷贝到对应XCode构建产物中,对应产物目录为:$HOME/Library/Developer/Xcode/DerivedData/${AppName}

上述两个静态库*.framework是拷贝到${BUILT_PRODUCTS_DIR}"/"${PRODUCT_NAME}".app/Frameworks"目录下

flutter_assets拷贝到${BUILT_PRODUCTS_DIR}"/"${PRODUCT_NAME}".app"目录下

在XCode工程中,对应的是在${AppName}/Products/${AppName}.app

五、Flutter与Native通信

Flutter与Native通信有三种方式,这里只简单介绍下:

  1. MethodChannel:方法调用
  2. EventChannel:事件监听
  3. BasicMessageChannel:消息传递

Flutter与Native通信都是双向通道,可以互相调用和消息传递

接下来是本文的重点内容,上述主要是普及下Flutter工程上比较重要的内容以及为下面要讲做准备,当然还有打包模式、构建流程等就不放这里了,后面可以单独开一篇讲

六、Flutter版本一致性与自动化管理

在团队多人协作开发模式下,Flutter SDK的版本一致性与自动化管理,这是个必须解决的问题,通过这个问题,我们回看Android中Gradle的版本管理模式:

Gradle的版本管理是通过包装器模式,每个Gradle项目都会对应一个Gradle构建版本,对应的Gradle版本在gradle-wrapper.properties配置文件中进行配置,如果执行构建时本地没有当前工程中对应的Gradle版本,则会自动下载所需的Gradle版本,而执行构建则是通过./gradlew包装器模式进行执行,这样本地配置的全局Gradle环境与工程环境即可隔离开,对应的项目始终保持同一个Gradle版本的构建

这种包装器模式的版本管理方式,可与每台机器中全局配置的环境保持隔离,在团队多人协作下,也可保持同一个项目工程保持同一个构建版本

所以,我们沿用Gradle版本管理思想,在每个Flutter工程(包含上述说的四种工程)的根目录加入三个文件:

wrapper/flutter-wrapper.properties
flutterw
flutterw.bat

加入后的项目结构则多了三个文件,如下: 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上述flutter-wrapper.properties为当前工程Flutter SDK版本配置文件,内容为:

distributionUrl=https://github.com/flutter/flutter
flutterVersion=1.0.0

当然有需要可以再增加一些配置,目前这两个配置已经足够了,指定了Flutter的远程地址以及版本号,如果Clone Github上项目比较慢,也可以改为私有维护的镜像地址

flutterw为一个Shell脚本,内部对版本管理主要做的事情为:

  1. 读取配置的版本号,校验Flutter SDK版本,不存在则触发下载
  2. 更新Android中local.properties和IOS中Generated.xcconfig文件中Flutter SDK地址
  3. 最后把命令行传来的参数链接到Flutter SDK中的flutter进行执行

之后构建Flutter工程则用flutterw命令:

./flutterw build bundle

而不用本地全局配置的flutter命令,避免每个开发同学版本不一致问题,且这种方式对于新加入Flutter开发的同学来说,完全不需要自己手动下载Flutter SDK,只需执行一下flutterw任何命令,如./flutterw --version,即可自动触发对应Flutter SDK的下载与安装,实现优雅的自动化管理,这种方式对打包平台来说也为支持Flutter工程的打包提供基础

七、Flutter混合开发组件化架构

上述说的如果我们要利用Flutter来开发我们现有Native工程中的一个模块或功能,肯定得不能改变Native的工程结构以及不影响现有的开发流程,那么,以何种方式进行混合开发呢? 前面说到Flutter的四种工程模型,Flutter App我们可以直接忽略,因为这是一个开发全新的Flutter App工程,对于Flutter Module,官方提供的本地依赖便是使用Flutter Module依赖到Native App的,而对于Flutter工程来说,构建Flutter工程必须得有个main.dart主入口,恰好Flutter Module中也有主入口

于是,我们进行组件划分,通过Flutter Module作为所有通过Flutter实现的模块或功能的聚合入口,通过它进行Flutter层到Native层的双向关联。而Flutter开发代码写在哪里呢?当然可以直接写在Flutter Module中,这没问题,而如果后续开发了多个模块、组件,我们的Dart代码总不可能全部写在Flutter Module中lib/吧,如果在lib/目录下再建立子目录进行模块区分,这不失为一种最简单的方式,不过这会带来一些问题,所有模块共用一个远程Git地址,首先在组件开发隔离上完全耦合了,其次各个模块组件没有单独的版本号或Tag,且

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值