refactor(core): Optimize and share network state flows (#4320)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-01-26 06:59:53 -06:00 committed by GitHub
parent 7ffd5bc9f2
commit fc5255a0f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 22 deletions

View file

@ -19,10 +19,16 @@ package com.geeksville.mesh.repository.network
import android.net.ConnectivityManager
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.shareIn
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.di.ProcessLifecycle
import javax.inject.Inject
import javax.inject.Singleton
@ -33,13 +39,35 @@ constructor(
private val nsdManagerLazy: dagger.Lazy<NsdManager>,
private val connectivityManager: dagger.Lazy<ConnectivityManager>,
private val dispatchers: CoroutineDispatchers,
@ProcessLifecycle private val processLifecycle: Lifecycle,
) {
val networkAvailable: Flow<Boolean>
get() = connectivityManager.get().networkAvailable().flowOn(dispatchers.io).conflate()
val networkAvailable: Flow<Boolean> by lazy {
connectivityManager
.get()
.networkAvailable()
.flowOn(dispatchers.io)
.conflate()
.shareIn(
scope = processLifecycle.coroutineScope,
started = SharingStarted.WhileSubscribed(5000),
replay = 1,
)
.distinctUntilChanged()
}
val resolvedList: Flow<List<NsdServiceInfo>>
get() = nsdManagerLazy.get().serviceList(SERVICE_TYPE).flowOn(dispatchers.io).conflate()
val resolvedList: Flow<List<NsdServiceInfo>> by lazy {
nsdManagerLazy
.get()
.serviceList(SERVICE_TYPE)
.flowOn(dispatchers.io)
.conflate()
.shareIn(
scope = processLifecycle.coroutineScope,
started = SharingStarted.WhileSubscribed(5000),
replay = 1,
)
}
companion object {
internal const val SERVICE_PORT = 4403

View file

@ -109,26 +109,34 @@ constructor(
*/
private var isStarted = false
private fun initStateListeners() {
bluetoothRepository.state
.onEach { state ->
if (state.enabled) {
startInterface()
} else if (radioIf is NordicBleInterface) {
stopInterface()
}
}
.launchIn(processLifecycle.coroutineScope)
@Volatile private var listenersInitialized = false
networkRepository.networkAvailable
.onEach { state ->
if (state) {
startInterface()
} else if (radioIf is TCPInterface) {
stopInterface()
private fun initStateListeners() {
if (listenersInitialized) return
synchronized(this) {
if (listenersInitialized) return
listenersInitialized = true
bluetoothRepository.state
.onEach { state ->
if (state.enabled) {
startInterface()
} else if (radioIf is NordicBleInterface) {
stopInterface()
}
}
}
.launchIn(processLifecycle.coroutineScope)
.launchIn(processLifecycle.coroutineScope)
networkRepository.networkAvailable
.onEach { state ->
if (state) {
startInterface()
} else if (radioIf is TCPInterface) {
stopInterface()
}
}
.launchIn(processLifecycle.coroutineScope)
}
}
companion object {