Skip to content

Commit b9ec7a0

Browse files
committed
chore: improve cold start and login performance
Defer all App Startup initializers off the main thread: - MnemonicCacheInitializer (disk read + SHA256) - TraceInitializer/Bugsnag.start() (release) - FirebaseInitializer, LibSodiumInitializer (already done) Tighten MainRoot splash timing: show logo immediately instead of after 1s delay, reduce spinner delay from 1.5s to 0.5s. Parallelize getUserFlags() and savePrefs() in AuthManager.login() so post-login navigation is faster. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent e91951c commit b9ec7a0

6 files changed

Lines changed: 45 additions & 26 deletions

File tree

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/startup/FirebaseInitializer.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ import com.flipcash.app.android.BuildConfig
66
import com.google.firebase.Firebase
77
import com.google.firebase.crashlytics.crashlytics
88
import com.google.firebase.initialize
9+
import kotlinx.coroutines.CoroutineScope
10+
import kotlinx.coroutines.Dispatchers
11+
import kotlinx.coroutines.launch
912

1013
class FirebaseInitializer: Initializer<Unit> {
1114
override fun create(context: Context) {
12-
Firebase.initialize(context)
13-
Firebase.crashlytics.isCrashlyticsCollectionEnabled = BuildConfig.NOTIFY_ERRORS || !BuildConfig.DEBUG
15+
CoroutineScope(Dispatchers.IO).launch {
16+
Firebase.initialize(context)
17+
Firebase.crashlytics.isCrashlyticsCollectionEnabled = BuildConfig.NOTIFY_ERRORS || !BuildConfig.DEBUG
18+
}
1419
}
1520

1621
override fun dependencies(): List<Class<out Initializer<*>?>?> {
1722
return emptyList()
1823
}
19-
}
24+
}

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/startup/LibSodiumInitializer.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ import androidx.startup.Initializer
55
import com.getcode.utils.TraceType
66
import com.getcode.utils.trace
77
import com.ionspin.kotlin.crypto.LibsodiumInitializer
8+
import kotlinx.coroutines.CoroutineScope
9+
import kotlinx.coroutines.Dispatchers
10+
import kotlinx.coroutines.launch
811

912
class LibSodiumInitializer: Initializer<Unit> {
1013
override fun create(context: Context) {
11-
LibsodiumInitializer.initializeWithCallback {
12-
trace("libsodium initialized", type = TraceType.Process)
14+
CoroutineScope(Dispatchers.IO).launch {
15+
LibsodiumInitializer.initializeWithCallback {
16+
trace("libsodium initialized", type = TraceType.Process)
17+
}
1318
}
1419
}
1520

1621
override fun dependencies(): List<Class<out Initializer<*>?>?> {
1722
return emptyList()
1823
}
19-
}
24+
}

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/startup/MnemonicCacheInitializer.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ package com.flipcash.app.internal.startup
33
import android.content.Context
44
import androidx.startup.Initializer
55
import com.getcode.crypt.MnemonicCache
6+
import kotlinx.coroutines.CoroutineScope
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.launch
69

710
class MnemonicCacheInitializer: Initializer<Unit> {
811
override fun create(context: Context) {
9-
MnemonicCache.init(context)
12+
CoroutineScope(Dispatchers.IO).launch {
13+
MnemonicCache.init(context)
14+
}
1015
}
1116

1217
override fun dependencies(): List<Class<out Initializer<*>?>?> {
1318
return emptyList()
1419
}
15-
}
20+
}

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/startup/TraceInitializer.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import android.content.Context
44
import androidx.startup.Initializer
55
import com.bugsnag.android.Bugsnag
66
import com.flipcash.app.android.BuildConfig
7+
import kotlinx.coroutines.CoroutineScope
8+
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.launch
710
import timber.log.Timber
811

912
class TraceInitializer: Initializer<Unit> {
@@ -32,11 +35,13 @@ class TraceInitializer: Initializer<Unit> {
3235
}
3336
})
3437
} else {
35-
Bugsnag.start(context)
38+
CoroutineScope(Dispatchers.IO).launch {
39+
Bugsnag.start(context)
40+
}
3641
}
3742
}
3843

3944
override fun dependencies(): List<Class<out Initializer<*>?>?> {
4045
return emptyList()
4146
}
42-
}
47+
}

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/MainRoot.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ internal fun MainRoot(deepLink: () -> DeepLink?) {
5050
val userManager = LocalUserManager.current!!
5151
var showLoading by remember { mutableStateOf(false) }
5252
val router = LocalRouter.current!!
53-
var showLogo by remember { mutableStateOf(false) }
53+
var showLogo by remember { mutableStateOf(true) }
5454
Box(
5555
modifier = Modifier
5656
.fillMaxSize()
@@ -86,11 +86,6 @@ internal fun MainRoot(deepLink: () -> DeepLink?) {
8686
}
8787

8888

89-
LaunchedEffect(Unit) {
90-
delay(1.seconds)
91-
showLogo = true
92-
}
93-
9489
LaunchedEffect(userManager) {
9590
userManager.state
9691
.map { it.authState to it.flags }
@@ -112,7 +107,7 @@ internal fun MainRoot(deepLink: () -> DeepLink?) {
112107

113108
when (state) {
114109
AuthState.LoggedInAwaitingUser -> {
115-
delay(1.5.seconds)
110+
delay(0.5.seconds)
116111
showLoading = true
117112
}
118113

apps/flipcash/shared/authentication/src/main/kotlin/com/flipcash/app/auth/AuthManager.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.google.firebase.messaging.FirebaseMessaging
2424
import com.google.firebase.messaging.messaging
2525
import kotlinx.coroutines.CoroutineScope
2626
import kotlinx.coroutines.Dispatchers
27+
import kotlinx.coroutines.coroutineScope
2728
import kotlinx.coroutines.launch
2829
import javax.inject.Inject
2930
import javax.inject.Singleton
@@ -155,16 +156,19 @@ class AuthManager @Inject constructor(
155156
persistence.openDatabase(entropyB64)
156157
userManager.set(accountId = account.id)
157158

158-
accountController.getUserFlags()
159-
.onSuccess { flags ->
160-
userManager.set(flags)
161-
userManager.set(if (flags.isRegistered) AuthState.LoggedInWithUser else AuthState.Registered())
162-
}.onFailure {
163-
taggedTrace("Failed to get user flags", type = TraceType.Error, cause = it)
164-
userManager.set(authState = AuthState.Registered())
159+
coroutineScope {
160+
launch {
161+
accountController.getUserFlags()
162+
.onSuccess { flags ->
163+
userManager.set(flags)
164+
userManager.set(if (flags.isRegistered) AuthState.LoggedInWithUser else AuthState.Registered())
165+
}.onFailure {
166+
taggedTrace("Failed to get user flags", type = TraceType.Error, cause = it)
167+
userManager.set(authState = AuthState.Registered())
168+
}
165169
}
166-
167-
savePrefs()
170+
launch { savePrefs() }
171+
}
168172
}.onFailure {
169173
logout()
170174
resetStateForUser()

0 commit comments

Comments
 (0)