教你如何使用 Flutter 和原生 App 混合开发 (1),Android 开发面试解答之 Handler
flutter create -t module {moduleName}
我这里创建一个 flutter 的模块项目叫 flutter_module
??flutter?create?-t?module?flutter_moduleCreating?project?flutter_module...flutter_module/test/widget_test.dart?(created)......flutter_module/.idea/workspace.xml?(created)Running?"flutter?packages?get"?in?flutter_module...?????????????????7.2sWrote?12?files.
All?done!Your?module?code?is?in?flutter_module/lib/main.dart.
创建成功后我们可以看一下目录结构
???flutter_module?git:(master)???tree?-L?2?-a.├──?.android│???├──?Flutter│???├──?app│???├──?...├──?.gitignore├──?.ios│???├──?Config│???├──?Flutter│???├──?...│???└──?Runner.xcworkspace├──?lib│???└──?main.dart├──?pubspec.lock├──?pubspec.yaml└──?test└──?widget_test.dart
在 flutter 的模块项目中包含有一个隐藏的.android 和.ios 目录这个目录下是可运行的 Android 和 iOS 项目,我们的 flutter 代码还是在 lib 下编写,注意在.android 和.ios 目录下都有一个 Flutter 目录,这个是我们 flutter 的库项目了。也就是 Android 用来生成 aar,iOS 用来生产 framework 的库。如果我们用 flutter create xxx 生成的纯 flutter 项目是没有这个 Flutter 目录的。
把该项目使用 git 管理起来,稍后我们要在 native 项目中以子模块的形式添加进去。
???cd?flutter_module???git?initInitialized?empty?Git?repository?in?/Users/zhiqiangdeng/Documents/ProjectSource/FlutterProject/flutter_module/.git/???flutter_module?git:(master)??
初始化 git 仓库后我们先编辑一下项目下的.gitignore
文件,当前这个文件是把项目下的.ios
和.android
忽略掉的。这个两个项目我们需要跟踪一下,大家可以去 github 上找一下 iOS 和 Android 的 gitignore 模版文件,然后添加到这个两个目录中,然后把顶层目录的文件作出如下修改,删除.android和.ios
添加.ios/Flutter/Generated.xcconfig。
.gitignore 文件:
-.android/-.ios/+.ios/Flutter/Generated.xcconfig
提交你的 flutter 模块项目到你的 git 服务器(我提交到 github 上了,大家可以参考)
git remote add origin {你的 flutter module 的仓库地址}git push origin master
给iOS项目集成flutter
进入我们原生的 iOS 项目根目录中,为它添加一个 git submodule,把我们的 flutter 项目拉取下来
git submodule add {你的 flutter module 的仓库地址}git submodule update
在项目的 Podfile 文件中添加下面的代码,在每次执行 pod install 会运行 podhelper.rb
platform?:ios,?'8.0'use_frameworks!
target?'MyApp'?dopod?'AFNetworking',?'~>?2.6'xxxxend#添加如下两行代码,路径修改为我们的 fluter?module 的路径 flutter_application_path?=?'./flutter-module-demo'eval(File.read(File.join(flutter_application_path,?'.ios',?'Flutter',?'podhelper.rb')),?binding)?
打开 Xcode 关闭 bitcode 配置 Build Settings->Build Options->Enable Bitcode
添加编译脚本,打开 Xcode 在 Build Phases 中添加 New Run Script Phase 在里面填入如下脚本
"FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"?embed
项目的配置完成现在需要生成一些配置文件
进入原生项目的 flutter 模块目录中执行 flutter packages get 命令
回到原生项目根目录执行 pod install
???cd?flutter-module-demo???flutter-module-demo?git:(master)?flutter?packages?getRunning?"flutter?packages?get"?in?flutter-module-demo...????????????0.4s???flutter-module-demo?git:(master)?cd?..???FlutterNativeiOS?git:(master)???pod?installAnalyzing?dependenciesFetching?podspec?for?Flutter
?from?./flutter-module-demo/.ios/Flutter/engine
Fetching?podspec?for?FlutterPluginRegistrant
?from?./flutter-module-demo/.ios/Flutter/FlutterPluginRegistrant
Downloading?dependenciesUsing?AFNetworking?(2.6.3)Installing?Flutter?(1.0.0)Installing?FlutterPluginRegistrant?(0.0.1)Generating?Pods?projectIntegrating?client?projectSending?statsPod?installation?complete!?There?are?3?dependencies?from?the?Podfile?and?3?total?pods?installed.
到此为止我们的原生项目就已经集成好了 flutter 项目了。
在原生项目中使用 flutter,下面以 swift 项目为例
修改 AppDelegate.swift:注意 AppDelegate 是集成自 FlutterAppDelegate
import?UIKitimport?Flutterimport?FlutterPluginRegistrant?//?Only?if?you?have?Flutter?Plugins.
@UIApplicationMainclass?AppDelegate:?FlutterAppDelegate?{var?flutterEngine?:?FlutterEngine?;//?Only?if?you?have?Flutter?plugins.override?func?application(_?application:?UIApplication,?didFinishLaunchingWithOptions?launchOptions:?[UIApplication.LaunchOptionsKey:?Any]?)?->?Bool?{self.flutterEngine?=?FlutterEngine(name:?"io.flutter",?project:?nil);self.flutterEngine?.run(withEntrypoint:?nil);GeneratedPluginRegistrant.register(with:?self.flutterEngine);return?super.application(application,?didFinishLaunchingWithOptions:?launchOptions);}
}
修改 Controller 代码
import?UIKitimport?Flutterclass?ViewController:?UIViewController?{override?func?viewDidLoad()?{super.viewDidLoad()let?button?=?UIButton(type:UIButtonType.custom)...self.view.addSubview(button)}
@objc?func?handleButtonAction()?{let?fl
utterEngine?=?(UIApplication.shared.delegate?as??AppDelegate)?.flutterEngine;let?flutterViewController?=?FlutterViewController(engine:?flutterEngine,?nibName:?nil,?bundle:?nil)!;self.present(flutterViewController,?animated:?true,?completion:?nil)}
RUN….
iOS项目集成过程梳理
整个的集成过程其实总得来说是如下三个步骤:
将 flutter 项目放入原生项目的文件夹下
在 podfile 中添加 podhelper.rb 配置
在 Xcode 的 build phases 添加"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh"iOS 编译脚本
其中 podhelper.rb 文件位于我们 flutter 模块项目的.ios/Flutter/podhelper.rb 下,大家查看它的源码可以发现,它有下面几个作用:
把 Flutter(flutterEngine)和 FlutterPluginRegistrant 两个库用 pod 给原生项目导入进入
如果 flutter 项目有用到 flutter plugin 插件,把插件用 pod 导入
导入 Generated.xcconfig 的相关配置信息,在 podhelper.rb 同级别的目录下还有一个 Generated.xcconfig 文件,这个文件在使用 flutter create xx、flutter run xxx、flutter packages get 命令的时候如果该文件不存在则会生成这个文件。这个文件内容如下:
//?This?is?a?generated?file;?do?not?edit?or?check?into?version?control.FLUTTER_ROOT=/Users/zhiqiangdeng/.flutter_wrapper/1.2.2-pre.43FLUTTER_APPLICATION_PATH=/Users/zhiqiangdeng/Documents/ProjectSource/XcodeProject/lianhua-order-iOS/order-check-module-flutterFLUTTER_TARGET=lib/main.dartFLUTTER_BUILD_DIR=buildSYMROOT=${SOURCE_ROOT}/../build/iosFLUTTER_BUILD_NAME=1.0.0FLUTTER_BUILD_NUMBER=1
他记录了当前 flutter sdk 的目录位置,以及版本号,还有项目模块的目录位置。这个文件的内容在执行pod install
的时候会被写入到 xcode build setting 中,在执行完 pod install 之后,可以在原生项目根目录使用xcodebuild -showBuildSettings|grep flutter
查看相关的信息。
最后一步就是运行程序,运行程序的时候在 Build phase 添加了 xcode_backend.sh 该脚本会使用到上面 pod install 给 xcode build setting 设置的那些环境变量,然后找到项目目录生成 AppFramework。
给原生Android项目集成Flutter
Android 的文章很多,这里不再详细描述了
在原生 Android 项目中添加子模块,将上面创建的 flutter module 项目拉取到原生安卓项目中
评论