在拥有了 Native 工程的情况下,开发者不太可能去创建一个全新的 Flutter 工程重写整个产品,因此Flutter工程将包含已有的 Native 工程,这样就带来了一系列问题:
- 构建打包问题: 引入Flutter后,Native 工程因对其有了依赖和耦合,从而无法独立编译构建。在 Flutter 环境下,工程的构建是从 Flutter 的构建命令开始,执行过程中包含了 Native 工程的构建,开发者要配置完整的 Flutter 运行环境才能走通整个流程;
- 混合编译带来的开发效率的降低: 在转型 Flutter 的过程中必然有许多业务仍使用 Native 进行开发,工程结构的改动会使开发无法在纯 Native 环境下进行,而适配到 Flutter 工程结构对纯Native 开发来说又会造成不必要的构建步骤,造成开发效率的降低。
期望
希望能够做到当项目混编的时候,没有开发 flutter 的同学能够完全脱离 flutter,不需要flutter 项目代码和安装 flutter 环境;而写 flutter 的团队成员能够按照原有的混编方式以方便开发和调试。
我们发现不管是 iOS 还是 Android 工程,依赖与 Flutter 的文件有:
- Flutter库和引擎:
Flutter.framework
- Flutter工程产物:
App.framework
- Flutter Plugin:编译出来的各种
plugin的framework
那我们只需要将这三部分的编译结果抽取出来,打包成一个 SDK 依赖的形式提供给 Native 工程,就可以解除 Native 工程对 Flutter 工程的直接依赖。
常见的引入方式
1.直接引入
原生项目通过cocoapods
直接引入,需要依赖 Flutter 环境,Podfile
里面的引入代码如下:
flutter_application_path = '../flutter_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
platform :ios, '9.0'
target 'NativeDemo' do
install_all_flutter_pods(flutter_application_path)
use_frameworks!
end
执行 pod install
打开原生工程进行使用
#import <Flutter/Flutter.h>
FlutterViewController *flutterVC = [[FlutterViewController alloc] init];
[self presentViewController:flutterVC animated:YES completion:nil];
2. Framework方式引入
通过命令把 flutter 工程编译成 framework
,然后引入原生工程中
flutter build ios-framework --output=../flutter_app
编译完成后,发现编译出了
Debug、Profile、Release
三种环境的framework
Debug
具备调试功能Profile
既具备debug的调试功能,又具备release的性能Release
发布环境
每个环境包含 App.xcframework
和Flutter.xcframework
,App.xcframework是我们的Flutter程序代码,Flutter.xcframework 包含Flutter的运行环境和引擎
这个时候让电脑上没有Flutter环境,看是否能正常跑Flutter代码?
在工程中添加framework
然后运行原生工程,发现是可以运行成功并且使用Flutter的。
3. Cocoapods 方式引入
进入flutter_module目录,然后编译
flutter build ios-framework --cocoapods --output=../flutter_app
发现也是编译出了三种环境,和编译Framework的区别是,flutter引擎是 Flutter.podspec
然后在原生工程通过 pod 引入:
pod 'Flutter',: podspec => 'flutter_app/Profile/Flutter.podspec'
原生工程添加 App.xcframework:
同样运行原生工程是没有问题的。
优化 Cocoapods 引入,实现工程自动化
一方面通过自动化减少人工成本,也减少人为失误。另一方面是做好版本控制,自动化的形式来做版本控制。
创建工程仓库
这个里面包含 原生 和 Flutter工程 代码
执行命令创建仓库:
这里会提示输入 github
账号和密码,现在都是采用 Token
配置密码了。进入 Settings->Developer settings
, 然后创建个人令牌
创建成功后复制 token,在终端粘贴回车
这时就可以看到成功创建了仓库了
添加原生工程到仓库
依次执行命令:
git add.
git commit -m ""
git push
成功后可以看到仓库里面就包含工程代码了
添加自动化脚本
脚本代码
这里是每次 push 代码脚本都会执行
name: FlutterCI #CI名称
on: [push] #触发条件push操作!
jobs:
check:
name: Test on ${{ matrix.os }}
#运行在哪个平台这里是MacOS平台
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
#三方flutter的Action,它可以在服务器配置一个Flutter环境
- uses: subosito/flutter-action@v1
with:
flutter-version: '2.5.3'
channel: 'stable'
#想让我们CI做的事情!
- run: cd flutter_module && flutter build ios-framework --cocoapods --output=../NativeDemo/Flutter
- run: |
git add .
git commit -m 'update flutter framework'
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
添加完脚本后可以看到正在编译Flutter工程了
编译完成了
这个时候可以看到原生项目里面多了一个Flutter文件夹,里面包含 Debug、Profile、Release
三个环境的framework。
拉取远程代码到本地
git pull
配置 cocoapods
到项目里面配置cocoapods,和上面通过cocoapods引入项目是一样的操作,在Podfile文件里面引入
platform :ios, '9.0'
target 'NativeDemo' do
use_frameworks!
pod 'Flutter',:podspec => 'Flutter/Debug/Flutter.podspec'
end
然后运行工程是没有问题的,说明配置成功了。然后依次执行
git add.
git commit -m ""
git push
push 成功后可以看到脚本又开始自动构建了
注意:这里只是一个简单的工程,假如大的原生项目嵌入Flutter我们要考虑的因素有很多,这里只是一个思路。每次发布上线的时候,记得选择 Release 里面的 framework。