From 8321df705a3899b464160cdc0cd48bbd8a217b3c Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Wed, 12 Aug 2026 18:04:26 +0000 Subject: [PATCH] perf(startup): move WorkManager and AppFunctions init off the main thread (#6648) Co-authored-by: Claude Fable 5 --- .../kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt | 4 +++- .../main/kotlin/org/meshtastic/app/MeshUtilApplication.kt | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt b/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt index 4fe3c23141..379127456d 100644 --- a/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt +++ b/androidApp/src/google/kotlin/org/meshtastic/app/GoogleMeshUtilApplication.kt @@ -17,6 +17,7 @@ package org.meshtastic.app import androidx.appfunctions.AppFunctionConfiguration +import kotlinx.coroutines.launch import org.koin.java.KoinJavaComponent.getKoin import org.meshtastic.app.ai.appfunctions.AppFunctionStateSync import org.meshtastic.app.ai.appfunctions.MeshtasticAppFunctions @@ -36,7 +37,8 @@ class GoogleMeshUtilApplication : // Start the AppFunctions enabled-state sync. Resolved here (after startKoin has bound // androidContext) rather than via createdAtStart so that Koin graphs built outside a // running app — verification tests, previews — stay lazily constructible. - getKoin().get() + // Off-main: construction forces the AppFunctionsPrefs subgraph and fires AppSearch binder calls. + applicationScope.launch { getKoin().get() } } override val appFunctionConfiguration: AppFunctionConfiguration diff --git a/androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt b/androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt index 8ecc1ecb24..587422d508 100644 --- a/androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt +++ b/androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt @@ -68,7 +68,7 @@ open class MeshUtilApplication : Configuration.Provider, SingletonImageLoader.Factory { - private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + protected val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) /** Supplies Coil's process-wide loader without retaining an Activity in its singleton factory. */ override fun newImageLoader(context: Context): ImageLoader = get() @@ -83,8 +83,9 @@ open class MeshUtilApplication : workManagerFactory() } - // Schedule periodic MeshLog cleanup - scheduleMeshLogCleanup() + // Schedule periodic MeshLog cleanup. Off-main: WorkManager uses on-demand init here + // (the startup provider is removed), so getInstance() opens WorkManager's Room DB. + applicationScope.launch { scheduleMeshLogCleanup() } // Generate and publish widget preview for Android 15+ widget picker if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {