我正在参与「启航计划」
1. FlutterEngine
flutter 作为模块嵌入iOS工程或者android工程。咱们能够参阅下官方文档, FlutterEngine
充当 Dart VM 和 Flutter 运行时的主机;FlutterViewController
依附于FlutterEngine
,给 Flutter 传递 UIKit 的输入事情,并展现被FlutterEngine
烘托的每一帧画面。
FlutterEngine文档
创立FlutterEngine:
import UIKit
import Flutter
// Used to connect plugins (only if you have plugins with iOS platform code).
import FlutterPluginRegistrant
@UIApplicationMain
class AppDelegate: FlutterAppDelegate { // More on the FlutterAppDelegate.
lazy var flutterEngine = FlutterEngine(name: "my flutter engine")
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Runs the default Dart entrypoint with a default Flutter route.
flutterEngine.run();
// Used to connect plugins (only if you have plugins with iOS platform code).
GeneratedPluginRegistrant.register(with: self.flutterEngine);
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}
运用
let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
let flutterViewController =
FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
present(flutterViewController, animated: true, completion: nil)
2. 加载多个modules
咱们想要加载多个modules的时候,测验运用在podfile文件中
flutter_application_path = '../../mall/mall_flutter_module'
flutter_application_path1 = '../../testModule'
load File.join(flutter_application_path,'.ios','Flutter','podhelper.rb')
load File.join(flutter_application_path1,'.ios','Flutter','podhelper.rb')
target 'xxx' do
install_all_flutter_pods(flutter_application_path)
install_all_flutter_pods(flutter_application_path1)
end
pod install
报错,已经导入了,之后我测验运用数组的形式inatll,也是无法install,之后进行下图操作
覆盖了之前的mallModul
- 手动增加 咱们增加flutter Module的时候也有手动的作用
flutter build ios-framework --output=some/path/MyApp/Flutter/
作用
some/path/MyApp/
└── Flutter/
├── Debug/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework (only if you have plugins with iOS platform code)
│ └── example_plugin.xcframework (each plugin is a separate framework)
├── Profile/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework
│ └── example_plugin.xcframework
└── Release/
├── Flutter.xcframework
├── App.xcframework
├── FlutterPluginRegistrant.xcframework
└── example_plugin.xcframework
一直运用相同目录下的Flutter.framework
和App.framework
。混合运用不同目录(例如Profile/Flutter.framework
以及Debug/App.framework
)将会导致运行失利。
Xcode工程增加
不论是运用framework仍是pods导入,实践上是导入上面的2个framework,包含flutter环境和app实践的代码
3. 解决方式
终究,与我的搭档评论了一切这些,他们主张测验将一切模块导入一个类似伞的项目中,然后导入到本机应用程序中。因此,我测验将这两个模块作为第三个模块的包导入,这里称为umbrella
:
umbrella/pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
login:
path: ../flutter_modules/login
register:
path: ../flutter_modules/register
那行得通,可是您有必要在模块中创立路由umbrella
以映射login
和register
小部件。
因此需求运用一个胶水项目,来管理这些module
创立一个胶水项目
void main() => runApp(UmbrellaApp(route: window.defaultRouteName));
class UmbrellaApp extends StatelessWidget {
final String route;
UmbrellaApp(this.route);
@override
Widget build(BuildContext context) {
switch (route) {
// UmbrellaModule is class holding static strings.
case UmbrellaModules.login: // UmbrellaModules.login = 'login_module'
return LoginModule();
case UmbrellaModules.register:
return RegisterModule();
default:
return ErrorRoute();
}
}
}
iOS 原生应用:
let flutterViewController = UmbrellaViewController()
flutterViewController.setInitialRoute("oobe_module")
self.present(flutterViewController, animated: false, completion: nil)
// UmbrellaViewController
class UmbrellaViewController: FlutterViewController
4.优化
在FlutterEngine
上调用run
,默认将会调用你的lib/main.dart
文件里的main()
函数。
你也能够运用另一个进口方法runWithEntrypoint
,并运用NSString
字符串指定一个不同的 Dart 进口。
运用
main()
以外的 Dart 进口函数,有必要运用下面的注解,避免被tree-shaken优化掉,而没有编译。
@pragma('vm:entry-point')
void myOtherEntrypoint() { ... };
别的,在指定 Dart 函数时,你能够指定特定文件的特定函数。
下面的例子运用lib/other_file.dart
文件的myOtherEntrypoint()
函数替代lib/main.dart
的main()
函数:
flutterEngine.run(withEntrypoint: "myOtherEntrypoint", libraryURI: "other_file.dart")
可是报错
**Dart Error: Dart_LookupLibrary: library 'other_file.dart' not found.**
咱们看官方注释
flutterEngine.run(withEntrypoint: entryPoint, libraryURI: ":package:multiple_flutters_module/other_file.dart")
可是仍是有点问题
2022-09-08 16:20:48.674755+0800 MultipleFluttersIos[17128:42337128] [VERBOSE-2:shell.cc(93)] Dart Error: Dart_LookupLibrary: library ‘:package:multiple_flutters_module/other_file.dart’ not found.
终究咱们运用在main函数中履行不同的进口
void main() => runApp(const MyApp(color: Colors.blue));
@pragma('vm:entry-point')
void topMain() => runApp(const MyApp(color: Colors.green));
@pragma('vm:entry-point')
void bottomMain() => runApp(const MyApp(color: Colors.purple));
在 Android 和 iOS 上增加多个 Flutter 实例的主要 API 是根据新的FlutterEngineGroup
类 (Android API,iOS API) 来创立FlutterEngine
的,而不是经过以前的FlutterEngine
结构。
尽管FlutterEngine
API 的用法简洁明了,但从FlutterEngineGroup
生成的FlutterEngine
具有常用同享资源(例如 GPU 上下文、字体衡量和阻隔线程的快照)的功能优势,然后加快首次烘托的速度、下降延迟并下降内存占用。
-
由
FlutterEngineGroup
生成的FlutterEngine
能够用来关联 UI 相关的类,例如FlutterActivity
或FlutterViewController
,与通常结构缓存的FlutterEngine
类似。 -
第一个
FlutterEngineGroup
生成的FlutterEngine
不需求持续保活,只要有 1 个可用的FlutterEngine
,就能够随时在各个FlutterEngine
之间同享资源。 -
经过
FlutterEngineGroup
生成的首个FlutterEngine
与运用从前的结构方法结构的FlutterEngine
有相同的功能特征。 -
当一切由
FlutterEngineGroup
结构的FlutterEngine
都被毁掉后,下一个创立的FlutterEngine
与首个创造的功能特征相同。 -
FlutterEngineGroup
本身不需求持续保活。将其毁掉后,已生成的FlutterEngine
不受影响,但无法持续在现有同享的基础上创立新引擎。
在delegate
let engines = FlutterEngineGroup(name: "multiple-flutters", project: nil)
初始化
class SingleFlutterViewController: FlutterViewController {
private var channel: FlutterMethodChannel?
init(withEntrypoint entryPoint: String?) {
let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
let newEngine = appDelegate.engines.makeEngine(withEntrypoint: entryPoint, libraryURI:nil)
GeneratedPluginRegistrant.register(with: newEngine)
super.init(engine: newEngine, nibName: nil, bundle: nil)
}
}
5 实践中的表现
展现flutter商城,并随意点击
终究稳定在430左右,最高441
初始化Engine
,不展现flutter商城页面
首页正常运用后增加内存
运用FlutterEngineGroup
加载测验模块
运用group 加载模块2
翻开商城运用独立的Engine
FlutterEngine(name: "io.flutter", project: nil)
内存运用情况会变大,此刻内存中加载了2个Engine
,3个烘托的FlutterViewController
模块全部运用group
切换模块一
切换模块三
没有明显的增加,由于flutter模块共用了一个烘托引擎,减少了内存压力,同时也方便处理以前的模块和新模块的联系。