refactor(deps): inject CoroutineDispatchers (#4170)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-01-08 17:40:26 -06:00 committed by GitHub
parent 68185460fa
commit 7744a42e1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 102 additions and 89 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Meshtastic LLC
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,7 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh
import android.content.Context
@ -31,6 +30,7 @@ import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.service.startService
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
import kotlinx.coroutines.launch
import org.meshtastic.core.service.IMeshService
import org.meshtastic.core.service.ServiceRepository
import javax.inject.Inject
@ -75,10 +75,12 @@ constructor(
super.onStart(owner)
Logger.d { "Lifecycle: ON_START" }
try {
bindMeshService()
} catch (ex: BindFailedException) {
Logger.e { "Bind of MeshService failed: ${ex.message}" }
owner.lifecycleScope.launch {
try {
bindMeshService()
} catch (ex: BindFailedException) {
Logger.e { "Bind of MeshService failed: ${ex.message}" }
}
}
}
@ -93,7 +95,7 @@ constructor(
// endregion
@Suppress("TooGenericExceptionCaught")
private fun bindMeshService() {
private suspend fun bindMeshService() {
Logger.d { "Binding to mesh service!" }
try {
MeshService.startService(context)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Meshtastic LLC
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,7 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh.android
import android.content.ComponentName
@ -25,6 +24,7 @@ import android.os.IBinder
import android.os.IInterface
import co.touchlab.kermit.Logger
import com.geeksville.mesh.util.exceptionReporter
import kotlinx.coroutines.delay
import java.io.Closeable
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
@ -64,7 +64,7 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
}
}
fun connect(c: Context, intent: Intent, flags: Int) {
suspend fun connect(c: Context, intent: Intent, flags: Int) {
context = c
if (isClosed) {
isClosed = false
@ -73,7 +73,7 @@ open class ServiceClient<T : IInterface>(private val stubFactory: (IBinder) -> T
// Try
// a short sleep to see if that helps
Logger.e { "Needed to use the second bind attempt hack" }
Thread.sleep(500) // was 200ms, but received an autobug from a Galaxy Note4, android 6.0.1
delay(500) // was 200ms, but received an autobug from a Galaxy Note4, android 6.0.1
if (!c.bindService(intent, connection, flags)) {
throw BindFailedException()
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Meshtastic LLC
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,7 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh.repository.radio
import android.app.Application
@ -31,7 +30,6 @@ import com.geeksville.mesh.repository.network.NetworkRepository
import com.geeksville.mesh.util.ignoreException
import com.geeksville.mesh.util.toRemoteExceptions
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.BufferOverflow
@ -99,7 +97,7 @@ constructor(
val mockInterfaceAddress: String by lazy { toInterfaceAddress(InterfaceId.MOCK, "") }
/** We recreate this scope each time we stop an interface */
var serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
var serviceScope = CoroutineScope(dispatchers.io + SupervisorJob())
private var radioIf: IRadioInterface = NopInterface("")
@ -292,7 +290,7 @@ constructor(
// cancel any old jobs and get ready for the new ones
serviceScope.cancel("stopping interface")
serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
serviceScope = CoroutineScope(dispatchers.io + SupervisorJob())
if (logSends) {
sentPacketsLog.close()

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Meshtastic LLC
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,7 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh.repository.radio
import co.touchlab.kermit.Logger
@ -23,9 +22,9 @@ import com.geeksville.mesh.repository.network.NetworkRepository
import com.geeksville.mesh.util.Exceptions
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import org.meshtastic.core.di.CoroutineDispatchers
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.IOException
@ -34,8 +33,13 @@ import java.net.InetAddress
import java.net.Socket
import java.net.SocketTimeoutException
class TCPInterface @AssistedInject constructor(service: RadioInterfaceService, @Assisted private val address: String) :
StreamInterface(service) {
class TCPInterface
@AssistedInject
constructor(
service: RadioInterfaceService,
private val dispatchers: CoroutineDispatchers,
@Assisted private val address: String,
) : StreamInterface(service) {
companion object {
const val MAX_RETRIES_ALLOWED = Int.MAX_VALUE
@ -143,7 +147,7 @@ class TCPInterface @AssistedInject constructor(service: RadioInterfaceService, @
}
// Create a socket to make the connection with the server
private suspend fun startConnect() = withContext(Dispatchers.IO) {
private suspend fun startConnect() = withContext(dispatchers.io) {
val attemptStart = System.currentTimeMillis()
Logger.i { "[$address] TCP connection attempt starting..." }

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025 Meshtastic LLC
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,7 +14,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.geeksville.mesh.ui.contact
import androidx.lifecycle.ViewModel
@ -30,7 +29,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.jetbrains.compose.resources.getString
import org.meshtastic.core.data.repository.NodeRepository
import org.meshtastic.core.data.repository.PacketRepository
@ -163,8 +161,8 @@ constructor(
longName = longName,
lastMessageTime = getShortDate(data.time),
lastMessageText = if (fromLocal) data.text else "$shortName: ${data.text}",
unreadCount = runBlocking(Dispatchers.IO) { packetRepository.getUnreadCount(contactKey) },
messageCount = runBlocking(Dispatchers.IO) { packetRepository.getMessageCount(contactKey) },
unreadCount = packetRepository.getUnreadCount(contactKey),
messageCount = packetRepository.getMessageCount(contactKey),
isMuted = settings[contactKey]?.isMuted == true,
isUnmessageable = user.isUnmessagable,
nodeColors =