Flutter集成CarPlay时AppDelegate初始化引擎致启动黑屏求助
解决Flutter集成CarPlay启动时黑屏问题
启动页和首个视图之间的黑屏,确实是因为FlutterEngine在主线程同步初始化阻塞了UI渲染,导致启动页消失后引擎还没准备好,出现空白期。以下是几个可行的解决方法:
1. 后台线程预加载Flutter引擎
把引擎的启动放到后台线程执行,避免阻塞主线程,同时等待引擎准备完成后再切换到Flutter页面:
修改你的AppDelegate代码:
let flutterEngine = FlutterEngine(name: "SharedEngine", project: nil, allowHeadlessExecution: true) @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, GCKLoggerDelegate{ let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID let kDebugLoggingEnabled = true private var engineIsReady = false override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 后台线程启动Flutter引擎,不卡主线程 DispatchQueue.global(qos: .userInitiated).async { self.flutterEngine.run() DispatchQueue.main.async { GeneratedPluginRegistrant.register(with: self.flutterEngine) self.engineIsReady = true self.switchToFlutterPage() } } let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID) let options = GCKCastOptions(discoveryCriteria: criteria) GCKCastContext.setSharedInstanceWith(options) GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true GCKLogger.sharedInstance().delegate = self return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func switchToFlutterPage() { guard engineIsReady, let window = self.window else { return } // 确认当前不是Flutter页面再切换 if !(window.rootViewController is FlutterViewController) { let flutterVC = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) window.rootViewController = flutterVC window.makeKeyAndVisible() } } // 兼容CarPlay启动场景,确保引擎就绪再处理 override func application(_ application: UIApplication, didConnectCarInterfaceController interfaceController: CPInterfaceController, to window: CPWindow) { if !engineIsReady { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.application(application, didConnectCarInterfaceController: interfaceController, to: window) } return } super.application(application, didConnectCarInterfaceController: interfaceController, to: window) } }
2. 延长启动页显示,添加平滑过渡
如果后台加载还是有短暂空白,可以自定义过渡页,保持启动页样式直到引擎就绪:
- 复制你的Launch Screen到一个新的ViewController(比如命名为SplashViewController)
- 在AppDelegate中先显示这个过渡页,等引擎准备好再切换到Flutter页面:
补充代码示例:
// 在AppDelegate中添加 private var splashVC: UIViewController? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 先显示过渡启动页 splashVC = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController() window?.rootViewController = splashVC window?.makeKeyAndVisible() // 后台启动引擎 DispatchQueue.global(qos: .userInitiated).async { self.flutterEngine.run() DispatchQueue.main.async { GeneratedPluginRegistrant.register(with: self.flutterEngine) self.engineIsReady = true self.switchToFlutterPage() } } // 其他Cast配置代码... return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func switchToFlutterPage() { guard engineIsReady, let window = self.window, let splashVC = splashVC else { return } let flutterVC = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) // 添加淡入过渡动画,避免生硬切换 splashVC.present(flutterVC, animated: true) { self.window?.rootViewController = flutterVC self.splashVC = nil } }
3. 优化引擎初始化速度
- 精简插件注册:检查
GeneratedPluginRegistrant.swift,只保留当前应用必需的插件注册代码,去掉无用插件 - 开启预编译:在Xcode的Build Settings中,找到
Flutter Enable Precompiled Flutter Libraries选项并设为Yes,加快引擎启动速度
内容的提问来源于stack exchange,提问作者Redc4ke
相关产品推荐
相关产品推荐

