本文先介绍一下现有工程如何集成 Flutter 实现混合开发,以及混合项目如何打包,再探索下如何降低原生和 Flutter 之间的依赖,使 Flutter 开发对原生开发的影响尽量降低,以及一些我在尝试中遇到的问题及解决。
介绍 Flutter
Flutter 是 Google 发布的一个用于创建跨平台、高性能移动应用的框架。Flutter 和 QT mobile 一样,都没有使用原生控件,相反都实现了一个自绘引擎,使用自身的布局、绘制系统。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台。Flutter 提供了丰富的组件、接口,开发者可以很快地为 Flutter 添加 Native 扩展。
前提工作
开发者需要安装好 Flutter 的环境,执行flutter doctor -v
验证。
验证通过后即可开始集成 Flutter。
现有原生工程集成 Flutter
最官方的教程应该是Add Flutter to existing apps了,按照教程如下一步步操作:
1.创建 flutter module
使用flutter create xxx
指令创建的 Flutter 项目包括用于 Flutter/Dart 代码的非常简单的工程。你可以修改 main.dart 的内容,以满足你的需要,并在此基础上进行构建。
假设你有一个已经存在 iOS 工程(以 flutterHybridDemo 为例)在some/path/flutterHybridDemo
,那么你新建的 flutter_module 和 iOS 工程应该在同一目录下(即都在 path 下)。
$ cd some/path/
$ flutter create -t module flutter_module
通过
shift+command+.
显示/隐藏隐藏文件夹
- lib/main.dart:存放的是 Dart 语言编写的代码,这里是核心代码;
- pubspec.yaml:配置依赖项的文件,比如配置远程 pub 仓库的依赖库,或者指定本地资源(图片、字体、音频、视频等);
- .ios/:iOS 部分代码;
- .android/:Android 部分代码;
- build/:存储 iOS 和 Android 构建文件;
- test/:测试代码。
2.将 flutter module 作为依赖添加到工程
假设文件夹结构如下:
some/path/
flutter_module/
lib/main.dart
.ios/
...
flutterHybridDemo/
flutterHybridDemo.xcodeproj
flutterHybridDemo/
AppDelegate.h
AppDelegate.m
...
集成 Flutter 框架需要使用CocoaPods
,这是因为 Flutter 框架还需要对 flutter_module 中可能包含的任何 Flutter 插件可用。
- 如果需要,请参考cocoapods.org了解如何在您的电脑上安装 CocoaPods。
创建 Podfile:
$ cd some/path/flutterHybridDemo
$ pod init
此时工程中会出现一个 Podfile 文件,添加项目依赖的第三方库就在这个文件中配置,编辑 Podfile 文件添加最后两行代码:
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'TestOne' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for TestOne
target 'TestOneTests' do
inherit! :search_paths
# Pods for testing
end
target 'TestOneUITests' do
inherit! :search_paths
# Pods for testing
end
end
#新添加的代码
flutter_application_path = '../flutter_module'
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
- 如果你的工程(flutterHybridDemo)已经在使用 Cocoapods ,你只需要做以下几件事来整合你的 flutter_module 应用程序:
(1)添加如下内容到 Podfile:
flutter_application_path = '../flutter_module'
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
(2)执行pod install
当你在some/path/flutter_module/pubspec.yaml
中修改 Flutter 插件依赖时,需要先执行flutter packages get
通过 podhelper.rb 脚本来刷新插件列表,然后再从some/path/flutterHybridDemo
执行一次pod install
。
podhelper.rb 脚本将确保你的插件和 Flutter 框架被添加到你的工程中,以及 bitcode 被禁用。
(3)禁用 bitcode
因为 Flutter 现在不支持 bitcode。需要设置 Build Settings->Build Options->Enable Bitcode 为 NO。
3.为编译 Dart 代码配置 build phase
打开 iOS 工程,选中项目的 Build Phases 选项,点击左上角+号按钮,选择 New Run Script Phase。
将下面的 shell 脚本添加到输入框中:
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
最后,确保 Run Script 这一行在 “Target dependencies” 或者 “Check Pods Manifest.lock” 后面。
至此,你可以编译一下工程确保无误:⌘B
。
4.在 iOS 工程中使用 FlutterViewController
首先声明你的 AppDelegate 是 FlutterAppDelegate 的子类。然后定义一个 FlutterEngine 属性,它可以帮助你注册一个没有 FlutterViewController 实例的插件。
在 AppDelegate.h:
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end
在AppDelegate.m,修改didFinishLaunchingWithOptions
方法如下:
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins
#include "AppDelegate.h"
@implementation AppDelegate
// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.flutterEngine = [[FlutterEngine alloc] initWithName:@