Android SDK中Flutter模块启动崩溃:缓存FlutterEngine不存在问题
解决FlutterEngineCache中请求的引擎不存在的偶现崩溃问题
问题概述
启动多模块Flutter SDK时出现偶现崩溃,Firebase显示约0.1%用户触发,错误信息:
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{package/io.flutter.embedding.android.FlutterActivity}: java.lang.IllegalStateException: The requested cached FlutterEngine did not exist in the FlutterEngineCache: 'my_engine_id'
当前代码逻辑为切换模块时先清空引擎缓存再创建新引擎,以此避免回到首次打开的模块;同时使用缓存引擎解决启动短暂空白屏问题。
崩溃原因分析
- 多线程竞争:FlutterEngineCache是全局单例,但缓存的
clear、put操作未加同步保护,多线程同时调用启动逻辑时,会出现缓存被意外清除的情况,导致后续启动Activity时找不到引擎。 - 生命周期未绑定:创建的FlutterEngine未关联Activity生命周期,可能被系统回收或在缓存操作完成前意外销毁。
- 检查与使用的时间窗口漏洞:缓存存在性检查完成后,到启动FlutterActivity的间隙,可能有其他操作移除了缓存引擎,导致最终启动时引擎不存在。
修复方案
1. 给缓存操作添加同步锁
确保缓存的clear、put、contains操作原子性,避免多线程竞争:
// 定义全局锁对象 private val engineCacheLock = Any() // 修改缓存操作代码 synchronized(engineCacheLock) { FlutterEngineCache.getInstance().clear() FlutterEngineCache.getInstance().put(ENGINE_ID, instance!!.flutterEngine) GeneratedPluginRegister.registerGeneratedPlugins(instance!!.flutterEngine) } // 检查缓存时同步加锁 synchronized(engineCacheLock) { if (baseActivity == null || !FlutterEngineCache.getInstance().contains(ENGINE_ID)) { FirebaseCrashlytics.getInstance().recordException(Throwable("Engine Id not found")) return false } }
2. 绑定FlutterEngine到Activity生命周期
避免引擎被意外回收,同时在Activity销毁时清理缓存和引擎:
if (activity != null) { instance!!.flutterEngine = FlutterEngine(activity) // 绑定生命周期,在Activity销毁时清理资源 activity.lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) synchronized(engineCacheLock) { FlutterEngineCache.getInstance().remove(ENGINE_ID) } instance!!.flutterEngine.destroy() } }) } else { val appContext = MyApplication.getInstance().currentActivity.applicationContext instance!!.flutterEngine = FlutterEngine(appContext) }
3. 优化模块切换逻辑,避免频繁清空缓存
当前清空全局缓存的逻辑是崩溃诱因之一,可通过两种方式优化:
方案A:复用引擎,传递模块参数切换页面
不需要清空缓存,复用已有引擎并向Dart侧传递模块参数,由Dart代码切换对应模块页面:// 复用引擎,执行Dart入口并传递模块参数 instance!!.flutterEngine.dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault(), arrayOf(moduleName) ) // 初始化对应模块的平台通道 when (moduleName) { Constant.MODULE1 -> Module1PlatformChannels(instance!!.flutterEngine, baseActivity!!).init() Constant.MODULE2 -> Module2PlatformChannels(instance!!.flutterEngine, baseActivity!!).init() }Dart侧接收参数初始化对应模块:
void main(List<String> args) { String initialModule = args.isNotEmpty ? args[0] : Constant.MODULE1; runApp(MyApp(initialModule: initialModule)); }方案B:为不同模块分配独立引擎ID
每个模块使用专属引擎ID,避免清空全局缓存:// 生成模块专属引擎ID private fun getEngineId(moduleName: String) = "engine_$moduleName" val engineId = getEngineId(moduleName) synchronized(engineCacheLock) { if (!FlutterEngineCache.getInstance().contains(engineId)) { val engine = FlutterEngine(activity ?: MyApplication.getInstance().currentActivity.applicationContext) engine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault()) FlutterEngineCache.getInstance().put(engineId, engine) GeneratedPluginRegister.registerGeneratedPlugins(engine) } } // 初始化对应模块通道 when (moduleName) { Constant.MODULE1 -> Module1PlatformChannels(FlutterEngineCache.getInstance().get(engineId)!!, baseActivity!!).init() Constant.MODULE2 -> Module2PlatformChannels(FlutterEngineCache.getInstance().get(engineId)!!, baseActivity!!).init() } // 启动对应缓存引擎的FlutterActivity return FlutterActivity.withCachedEngine(engineId).build(context)
4. 增加启动前二次兜底检查
在构建FlutterActivity Intent前再次确认引擎存在,避免检查与启动之间的间隙出现异常:
val intent = synchronized(engineCacheLock) { if (!FlutterEngineCache.getInstance().contains(ENGINE_ID)) { // 兜底重建引擎并放入缓存 instance!!.flutterEngine = FlutterEngine(activity ?: MyApplication.getInstance().currentActivity.applicationContext) instance!!.flutterEngine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault()) FlutterEngineCache.getInstance().put(ENGINE_ID, instance!!.flutterEngine) GeneratedPluginRegister.registerGeneratedPlugins(instance!!.flutterEngine) } FlutterActivity.withCachedEngine(ENGINE_ID).build(context) } return intent
内容的提问来源于stack exchange,提问作者Sonu Kumar
相关产品推荐
相关产品推荐

