[Fix] Scanner item flicker
This commit is contained in:
+19
-7
@@ -37,6 +37,7 @@ import kotlinx.coroutines.withTimeout
|
|||||||
import kotlinx.coroutines.TimeoutCancellationException
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import kotlin.time.TimeSource
|
import kotlin.time.TimeSource
|
||||||
import kotlin.uuid.ExperimentalUuidApi
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
@@ -45,6 +46,10 @@ data class ConnectedDevice(
|
|||||||
val advertisement: Advertisement,
|
val advertisement: Advertisement,
|
||||||
val state: State
|
val state: State
|
||||||
)
|
)
|
||||||
|
data class AdvertisementMark(
|
||||||
|
val advertisement: Advertisement,
|
||||||
|
val timeMark: TimeSource.Monotonic.ValueTimeMark
|
||||||
|
)
|
||||||
@OptIn(ExperimentalUuidApi::class)
|
@OptIn(ExperimentalUuidApi::class)
|
||||||
class ScannerViewModel(
|
class ScannerViewModel(
|
||||||
private val bleManager: BleManager,
|
private val bleManager: BleManager,
|
||||||
@@ -54,7 +59,7 @@ class ScannerViewModel(
|
|||||||
private val scannerRepository: ScannerRepository
|
private val scannerRepository: ScannerRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
private val SCAN_TIMEOUT = 1.seconds
|
private val SCAN_TIMEOUT = 5.seconds
|
||||||
private val CONNECTION_TIMEOUT = 5.seconds
|
private val CONNECTION_TIMEOUT = 5.seconds
|
||||||
private const val MAX_LOG_ENTRIES = 50
|
private const val MAX_LOG_ENTRIES = 50
|
||||||
}
|
}
|
||||||
@@ -79,7 +84,7 @@ class ScannerViewModel(
|
|||||||
private var cleanupJob: Job? = null
|
private var cleanupJob: Job? = null
|
||||||
private val connectionJobs = mutableMapOf<String, Job>()
|
private val connectionJobs = mutableMapOf<String, Job>()
|
||||||
|
|
||||||
private val advertisementMap = mutableMapOf<String, Pair<Advertisement, TimeSource.Monotonic.ValueTimeMark>>()
|
private val advertisementMap = mutableMapOf<String, AdvertisementMark>()
|
||||||
|
|
||||||
/** Bonded device */
|
/** Bonded device */
|
||||||
private val bondedIds = mutableSetOf<String>() // Cache
|
private val bondedIds = mutableSetOf<String>() // Cache
|
||||||
@@ -118,7 +123,12 @@ class ScannerViewModel(
|
|||||||
connect(advertisement)
|
connect(advertisement)
|
||||||
} else {
|
} else {
|
||||||
val now = TimeSource.Monotonic.markNow()
|
val now = TimeSource.Monotonic.markNow()
|
||||||
advertisementMap[advertisement.identifier.toString()] = advertisement to now
|
val entry = advertisementMap[bleId]
|
||||||
|
if (entry != null) {
|
||||||
|
advertisementMap[bleId] = entry.copy(advertisement = advertisement, timeMark = now)
|
||||||
|
} else {
|
||||||
|
advertisementMap[bleId] = AdvertisementMark(advertisement, now)
|
||||||
|
}
|
||||||
startCleanupJob()
|
startCleanupJob()
|
||||||
updateDeviceList()
|
updateDeviceList()
|
||||||
}
|
}
|
||||||
@@ -131,8 +141,8 @@ class ScannerViewModel(
|
|||||||
if (cleanupJob?.isActive == true) return
|
if (cleanupJob?.isActive == true) return
|
||||||
cleanupJob = viewModelScope.launch {
|
cleanupJob = viewModelScope.launch {
|
||||||
while (advertisementMap.isNotEmpty() && isActive) {
|
while (advertisementMap.isNotEmpty() && isActive) {
|
||||||
delay(1000)
|
delay(5000)
|
||||||
val keysToRemove = advertisementMap.filter { it.value.second.elapsedNow() > SCAN_TIMEOUT }.keys
|
val keysToRemove = advertisementMap.filter { it.value.timeMark.elapsedNow() > SCAN_TIMEOUT }.keys
|
||||||
if (keysToRemove.isNotEmpty()) {
|
if (keysToRemove.isNotEmpty()) {
|
||||||
keysToRemove.forEach { advertisementMap.remove(it) }
|
keysToRemove.forEach { advertisementMap.remove(it) }
|
||||||
updateDeviceList()
|
updateDeviceList()
|
||||||
@@ -147,8 +157,10 @@ class ScannerViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDeviceList() {
|
private fun updateDeviceList() {
|
||||||
_devices.value = advertisementMap.values.map { it.first }
|
val newList = advertisementMap.values.map { it.advertisement }
|
||||||
// .sortedByDescending { it.rssi } // Fix flicker
|
if (newList != _devices.value) {
|
||||||
|
_devices.value = newList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopScan() {
|
fun stopScan() {
|
||||||
|
|||||||
Reference in New Issue
Block a user