本篇博客会介绍如何通过第三方插件Flutter_Boost
实现接入原有工程。
如果不希望引入第三方插件,可以参考博客Flutter混合开发--接入现有原生工程(iOS+Android)
一、新建原生工程和Flutter Module
1、新建Android工程
搭建一个空的Android工程FlutterDemo_Android
模拟已经存在的原有工程
Android项目配置:

2、新建iOS工程
搭建一个空的iOS工程FlutterDemo_iOS
模拟已经存在的原有工程
Xcode项目配置

搭建Pod:
在工程目录下执行
3、新建Flutter Module
这里使用AndroidStudio做Flutter开发环境
3.1 AndroidStudio添加Flutter插件

3.2 新建Flutter Module
第一步:File -> New Flutter Project

第二步:选择Flutter

第三步:配置Flutter Module
flutter_demo_module

完成目录结构

二、Flutter Boost 配置
1、Flutter_Module工程
1.修改pubspec.yaml文件:
| dependencies: |
| flutter: |
| sdk: flutter |
| cupertino_icons: ^1.0.2 |
| |
| |
| flutter_boost: |
| git: |
| url: 'https://github.com/alibaba/flutter_boost.git' |
| ref: '4.1.0' |
然后执行flutter pub get
下载flutter_boost到module中
2.新增willpop.dart页面做为跳转目标页
| import 'package:flutter/material.dart'; |
| |
| class WillPopRoute extends StatefulWidget { |
| const WillPopRoute({Key? key, this.title}) : super(key: key); |
| |
| final String? title; |
| |
| @override |
| State<StatefulWidget> createState() => _WillPopRouteState(); |
| } |
| |
| class _WillPopRouteState extends State<WillPopRoute> { |
| bool shouldPop = true; |
| @override |
| Widget build(BuildContext context) { |
| return WillPopScope( |
| onWillPop: () async { |
| return shouldPop; |
| }, |
| child: Scaffold( |
| appBar: AppBar( |
| title: const Text('Flutter Demo'), |
| ), |
| ), |
| ); |
| } |
| } |
3.修改main.dart文件,配置页面路由
| import 'package:flutter/material.dart'; |
| import 'package:flutter_boost/flutter_boost.dart'; |
| import 'package:flutter_demo_module/willpop.dart'; |
| |
| void main() { |
| CustomFlutterBinding(); |
| runApp(const MyApp()); |
| } |
| |
| class CustomFlutterBinding extends WidgetsFlutterBinding |
| with BoostFlutterBinding {} |
| |
| |
| class MyApp extends StatefulWidget { |
| const MyApp({super.key}); |
| |
| @override |
| State<MyApp> createState() => _MyAppState(); |
| } |
| |
| class _MyAppState extends State<MyApp> { |
| |
| static Map<String, FlutterBoostRouteFactory> routerMap = { |
| 'flutterPage': (settings, uniqueId) { |
| return PageRouteBuilder<dynamic>( |
| settings: settings, pageBuilder: (_, __, ___) => const WillPopRoute()); |
| } |
| }; |
| |
| Route<dynamic>? routeFactory(RouteSettings settings, String? uniqueId) { |
| FlutterBoostRouteFactory? func = routerMap[settings.name!]; |
| if (func == null) { |
| return null; |
| } |
| return func(settings, uniqueId); |
| } |
| |
| @override |
| void initState() { |
| super.initState(); |
| } |
| @override |
| Widget build(BuildContext context) { |
| return FlutterBoostApp(routeFactory); |
| } |
| |
| } |
2、Android跳转Flutter:
1.setting.gralde添加:
| setBinding(new Binding([gradle: this])) |
| evaluate(new File( |
| settingsDir.parentFile, |
| 'flutter_demo_module/.android/include_flutter.groovy' |
| )) |
| include ':flutter_demo_module' |
| project(':flutter_demo_module').projectDir = new File('../flutter_demo_module') |
注意:new Binding([gradle: this])
会有红色提示,不用管
2.app的AndroidManifest添加:
| <activity |
| android:name="com.idlefish.flutterboost.containers.FlutterBoostActivity" |
| android:theme="@style/Theme.AppCompat" |
| android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" |
| android:hardwareAccelerated="true" |
| android:windowSoftInputMode="adjustResize" > |
| |
| </activity> |
| <meta-data android:name="flutterEmbedding" |
| android:value="2"> |
| </meta-data> |
注意这一步之后执行gradle sync,如果遇到问题,可以参考文章最后的问题集锦
3.FlutterBoost初始化
自定义Application
| class MyApp : Application() { |
| override fun onCreate() { |
| super.onCreate() |
| FlutterBoost.instance().setup(this, object : FlutterBoostDelegate { |
| override fun pushNativeRoute(options: FlutterBoostRouteOptions) { |
| |
| } |
| |
| override fun pushFlutterRoute(options: FlutterBoostRouteOptions) { |
| |
| } |
| }, FlutterBoost.Callback { engine: FlutterEngine? -> }) |
| } |
| } |
配置app的AndroidManifest
| <application |
| android:name=".MyApp" |
| ... |
| </application> |
4.Android跳转代码
| val params: Map<String, Any> = HashMap() |
| val intent: Intent = FlutterBoostActivity.CachedEngineIntentBuilder( |
| FlutterBoostActivity::class.java |
| ) |
| .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.opaque) |
| .destroyEngineWithActivity(false) |
| .url("flutterPage") |
| .urlParams(params) |
| .build(context) |
| startActivity(intent) |
3、iOS跳转Flutter:
1.修改Pod文件
step1. load file
| flutter_application_path = '../flutter_demo_module' |
| load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') |
step2. install function
| install_all_flutter_pods(flutter_application_path) |
step3 post_install
| post_install do |installer| |
| flutter_post_install(installer) if defined?(flutter_post_install) |
| end |
完整pod文件
| |
| |
| flutter_application_path = '../flutter_demo_module' |
| load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') |
| |
| target 'FlutterDemo_iOS' do |
| |
| use_frameworks! |
| |
| |
| install_all_flutter_pods(flutter_application_path) |
| end |
| |
| |
| post_install do |installer| |
| flutter_post_install(installer) if defined?(flutter_post_install) |
| end |
执行pod install
,podhelper.rb 脚本会把你的 plugins, Flutter.framework,和 App.framework 集成到你的项目中。
备注:
Flutter.framework
是 Flutter engine 的框架, App.framework
是你的 Dart 代码的编译产物。
2.添加Delegate
定义FlutterDelegate
| import UIKit |
| import Flutter |
| import flutter_boost |
| import FlutterPluginRegistrant |
| |
| |
| class MyBoostAppDelegate: NSObject,FlutterBoostDelegate { |
| |
| static let shared = MyBoostAppDelegate() |
| |
| |
| var navigationController:UINavigationController? |
| |
| |
| var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:]; |
| |
| func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) { |
| |
| |
| let isPresent = arguments["isPresent"] as? Bool ?? false |
| let isAnimated = arguments["isAnimated"] as? Bool ?? true |
| |
| let targetViewController = UIViewController() |
| |
| if(isPresent){ |
| self.navigationController?.present(targetViewController, animated: isAnimated, completion: nil) |
| }else{ |
| self.navigationController?.pushViewController(targetViewController, animated: isAnimated) |
| } |
| } |
| |
| func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) { |
| let vc:FBFlutterViewContainer = FBFlutterViewContainer() |
| vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque) |
| |
| |
| let isPresent = (options.arguments?["isPresent"] as? Bool) ?? false |
| let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true |
| |
| |
| resultTable[options.pageName] = options.onPageFinished; |
| |
| |
| if(isPresent || !options.opaque){ |
| self.navigationController?.present(vc, animated: isAnimated, completion: nil) |
| }else{ |
| self.navigationController?.pushViewController(vc, animated: isAnimated) |
| } |
| } |
| |
| func popRoute(_ options: FlutterBoostRouteOptions!) { |
| |
| if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId{ |
| |
| |
| |
| if vc.modalPresentationStyle == .overFullScreen { |
| |
| |
| self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false) |
| |
| vc.dismiss(animated: true) { |
| self.navigationController?.topViewController?.endAppearanceTransition() |
| } |
| }else{ |
| |
| vc.dismiss(animated: true, completion: nil) |
| } |
| }else{ |
| self.navigationController?.popViewController(animated: true) |
| } |
| |
| |
| if let onPageFinshed = resultTable[options.pageName] { |
| onPageFinshed(options.arguments) |
| resultTable.removeValue(forKey: options.pageName) |
| } |
| } |
| } |
修改AppDelegate
| import UIKit |
| import flutter_boost |
| |
| @main |
| class AppDelegate: UIResponder, UIApplicationDelegate { |
| |
| func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { |
| |
| |
| let delegate = MyBoostAppDelegate.shared |
| FlutterBoost.instance().setup(application, delegate: delegate) { engine in |
| |
| } |
| return true |
| } |
| } |
| |
跳转Flutter页面代码
| @IBAction func clickButton(_ sender: Any) { |
| MyBoostAppDelegate.shared.navigationController = self.navigationController |
| let options = FlutterBoostRouteOptions() |
| options.pageName = "flutterPage" |
| FlutterBoost.instance().open(options) |
| } |
问题集锦
1.Android导入Flutter Module报错Failed to apply plugin class ‘FlutterPlugin’
setting.gradle修改Model值为RepositoriesMode.PREFER_PROJECT
| dependencyResolutionManagement { |
| repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) |
| repositories { |
| google() |
| mavenCentral() |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探