@@ -2,38 +2,61 @@ package com.aquib.androidperflab
22
33import android.app.Application
44import android.util.Log
5- import com.aquib.androidperflab.sdk.FakeAnalyticsSdk
6- import com.aquib.androidperflab.sdk.FakeCrashReportingSdk
7- import com.aquib.androidperflab.sdk.FakeFeatureFlagsSdk
8- import com.aquib.androidperflab.sdk.FakePerformanceMonitorSdk
9- import com.aquib.androidperflab.sdk.FakeRemoteConfigSdk
5+ import androidx.startup.AppInitializer
6+ import com.aquib.androidperflab.startup.AnalyticsInitializer
7+ import com.aquib.androidperflab.startup.FeatureFlagsInitializer
8+ import com.aquib.androidperflab.startup.PerfMonitorInitializer
9+ import com.aquib.androidperflab.startup.RemoteConfigInitializer
10+ import kotlinx.coroutines.CoroutineScope
11+ import kotlinx.coroutines.Dispatchers
12+ import kotlinx.coroutines.SupervisorJob
13+ import kotlinx.coroutines.delay
14+ import kotlinx.coroutines.launch
1015
1116class AndroidPerfLabApplication : Application () {
1217
18+ // Initialized at property-declaration time (before Application.onCreate and before
19+ // ContentProviders start). CrashReportingInitializer accesses this scope to fire
20+ // its background upload job — which is why it must be a property, not set in onCreate.
21+ // SupervisorJob: a failing child coroutine does not cancel sibling coroutines.
22+ val applicationScope = CoroutineScope (SupervisorJob () + Dispatchers .Default )
23+
1324 override fun onCreate () {
1425 super .onCreate()
15-
16- // Intentionally bad: all five SDKs are initialised synchronously on the main thread.
17- // Each blocks via Thread.sleep() to simulate the I/O, disk, and network work that
18- // real SDKs perform. Total cold-start penalty ≈ 750 ms before the first frame.
19-
2026 val t0 = System .currentTimeMillis()
2127
22- FakeCrashReportingSdk .init (this ) // ~120 ms — must be first to catch early crashes
23- Log .d(" AppStartup" , " CrashReporting ready +${System .currentTimeMillis() - t0} ms" )
24-
25- FakeAnalyticsSdk .init (this ) // ~180 ms
26- Log .d(" AppStartup" , " Analytics ready +${System .currentTimeMillis() - t0} ms" )
27-
28- FakeFeatureFlagsSdk .init (this ) // ~150 ms
29- Log .d(" AppStartup" , " FeatureFlags ready +${System .currentTimeMillis() - t0} ms" )
30-
31- FakeRemoteConfigSdk .init (this ) // ~200 ms
32- Log .d(" AppStartup" , " RemoteConfig ready +${System .currentTimeMillis() - t0} ms" )
33-
34- FakePerformanceMonitorSdk .init (this ) // ~100 ms — last so it can baseline the others
35- Log .d(" AppStartup" , " PerfMonitor ready +${System .currentTimeMillis() - t0} ms" )
28+ // CrashReportingInitializer ran synchronously via InitializationProvider BEFORE
29+ // this method. The exception handler is already registered; its upload coroutine
30+ // is already running on Dispatchers.IO. Nothing to do here for crash reporting.
31+ val appInit = AppInitializer .getInstance(this )
32+
33+ // Non-critical SDKs (Analytics, PerfMonitor): launch immediately on IO.
34+ // AppInitializer.initializeComponent() is idempotent — safe to call even if
35+ // a dependency was already initialized via the manifest.
36+ // Both SDKs initialize in ~180 ms + ~100 ms but never touch the main thread.
37+ applicationScope.launch(Dispatchers .IO ) {
38+ appInit.initializeComponent(AnalyticsInitializer ::class .java)
39+ // PerfMonitor declares Analytics as a dependency in the initializer graph,
40+ // so AppInitializer will invoke Analytics.create() first automatically —
41+ // the explicit sequence here is just for clarity.
42+ appInit.initializeComponent(PerfMonitorInitializer ::class .java)
43+ }
44+
45+ // Lazy SDKs (FeatureFlags, RemoteConfig): deferred by 500 ms so they never
46+ // compete with Compose's first layout-and-draw pass. Both SDKs return safe
47+ // defaults until their background coroutines complete, so the UI is never gated
48+ // on their initialization.
49+ applicationScope.launch(Dispatchers .IO ) {
50+ delay(500L )
51+ appInit.initializeComponent(FeatureFlagsInitializer ::class .java)
52+ appInit.initializeComponent(RemoteConfigInitializer ::class .java)
53+ }
54+
55+ Log .d(TAG , " Application.onCreate() returned in ${System .currentTimeMillis() - t0} ms " +
56+ " — all SDKs initializing in background" )
57+ }
3658
37- Log .d(" AppStartup" , " Application.onCreate() complete — total blocked=${System .currentTimeMillis() - t0} ms" )
59+ companion object {
60+ private const val TAG = " AppStartup"
3861 }
3962}
0 commit comments