教你如何使用 Flutter 和原生 App 混合开发,androidstudio 项目实战
方案选择
目前主流的混合开发方案有两种集成方式:
源码集成
也就是谷歌官方提供的方案,项目地址如下所示:
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps
产物集成
Flutter 项目单独开发,开发完成后发布成 aar 包或者 iOS 的 framework 形式,原生项目依赖 flutter 输出的制品即可。具体可以参考闲鱼的文章。
两种方式各有优劣,其实产物集成更好一些,不过即使是进行产物集成,也需要弄懂源码集成的方式,因为当有很多和原生交互的功能进行开发的时候,源码集成的方式可以直接调试会方便很多。
根据目前我们的情况:
参与人员都要进行 flutter 开发
持续发布和构建我可以修改控制
我们现在这个项目选择了源码集成的方式。
为原生项目集成 flutter
整个的集成方案是参考谷歌方法,但是有一些不一样,我是创建了一个 flutter 项目后,在原生的项目中使用 git submodule 的形式进行管理的。
创建flutter module project
我们假定已经有了原生的项目 Native-iOS 和 Native-Android;现在我们需要创建我们的 flutter 项目。
把我们的 flutter 的 channel 切换到 master(master 分支下是 flutter 的 preview 版本)
flutter channel master
创建 flutter 模块的项目
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(_?applic
ation:?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?flutterEngine?=?(UIApplication.shared.delegate?as??AppDelegate)?.flutterEngine;let?flutterViewController?=?FlutterViewController(engine:?flutterEngine,?nibName:?nil,?bundle:?nil)!;self.present(flutterViewController,?animated:?true,?completion:?nil)}
评论