fix: Resolve ANR during app initialization with 930+ peer identities

Move peer identity restoration to IO dispatcher to prevent blocking
main thread during JSON serialization. Also move interface status
polling to IO dispatcher to fix network status screen lag.

Changes:
- ColumbaApplication: Run restorePeerIdentities on Dispatchers.IO
- InterfaceManagementViewModel: Add injectable ioDispatcher for polling
- ConversationRepository: Remove per-identity logging (930 log calls)
- Update tests to inject test dispatcher for IO operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
torlando-tech
2025-12-14 00:50:46 -05:00
parent 271a9e3afb
commit be9e9a512d
4 changed files with 12 additions and 7 deletions

View File

@@ -349,7 +349,8 @@ class ColumbaApplication : Application() {
}
// Restore peer identities from database to enable message sending
applicationScope.launch {
// Run on IO dispatcher to avoid blocking main thread during JSON serialization
applicationScope.launch(kotlinx.coroutines.Dispatchers.IO) {
try {
val peerIdentities = conversationRepository.getAllPeerIdentities()
if (peerIdentities.isNotEmpty()) {

View File

@@ -119,6 +119,9 @@ class InterfaceManagementViewModel
// Made internal var (not const) to allow disabling polling in tests
internal var STATUS_POLL_INTERVAL_MS = 3000L
// Made internal var to allow injecting test dispatcher
internal var ioDispatcher: kotlinx.coroutines.CoroutineDispatcher = Dispatchers.IO
}
private val _state = MutableStateFlow(InterfaceManagementState())
@@ -158,7 +161,7 @@ class InterfaceManagementViewModel
Log.d(TAG, "Polling disabled (interval <= 0)")
return
}
viewModelScope.launch {
viewModelScope.launch(ioDispatcher) {
while (true) {
try {
fetchInterfaceStatus()
@@ -184,7 +187,7 @@ class InterfaceManagementViewModel
return
}
viewModelScope.launch {
viewModelScope.launch(ioDispatcher) {
serviceProtocol.interfaceStatusChanged.collect {
Log.d(TAG, "████ INTERFACE STATUS EVENT ████ Triggering immediate refresh")
try {

View File

@@ -59,6 +59,9 @@ class InterfaceManagementViewModelStatusEventTest {
// CRITICAL: Disable polling to prevent OOM in tests
InterfaceManagementViewModel.STATUS_POLL_INTERVAL_MS = 0
// Use test dispatcher for IO operations
InterfaceManagementViewModel.ioDispatcher = testDispatcher
interfaceRepository = mockk()
configManager = mockk()
bleStatusRepository = mockk()
@@ -97,6 +100,8 @@ class InterfaceManagementViewModelStatusEventTest {
viewModel.viewModelScope.cancel()
}
Dispatchers.resetMain()
// Reset IO dispatcher to default
InterfaceManagementViewModel.ioDispatcher = Dispatchers.IO
clearAllMocks()
// Reset polling interval to default
InterfaceManagementViewModel.STATUS_POLL_INTERVAL_MS = 3000L

View File

@@ -382,10 +382,6 @@ class ConversationRepository
val identitiesWithKeys =
allPeerIdentities.map { peerIdentity ->
android.util.Log.d(
"ConversationRepository",
"Peer ${peerIdentity.peerHash}: has public key, length=${peerIdentity.publicKey.size}",
)
peerIdentity.peerHash to peerIdentity.publicKey
}