Trying to implement a real time graph for sensor data in Jetpack Compose, but I am struggling with the correct way to pass the sensor data to the graph.
The app is receiving new sensor data over BLE every 40ms in a Kotlin class, and I would like to pass these to a custom Compose Line Chart. I tried implementing it with a Stateflow, which is then collected in the Composable to fill a list, but this is too slow:
DataReceiver:
private val _liveData = MutableStateFlow(0)
// The UI collects from this StateFlow to get its state updates
val liveData: StateFlow<Int> = _liveData
override fun onCharacteristicChanged(
characteristic: BluetoothGattCharacteristic,
value: ByteArray,
) {
_liveData.value = value[0].toInt()
}
This part works fine and the data is set to the liveData value. But when I try to collect this from the composable e.g.:
LaunchedEffect(DataReceiver.liveData) {
DataReceiver.liveData
.collect {
Log.d("BLE", "Value: " + it.value.toString())
}
}
I am missing some values, like this is not fast enough to capture all the data from the flow?
How can I improve this or what is the best way to receive these values from an event and add it to a list in a composable?
Based on the suggestions by @Leviathan I came up with this solution, in case anyone looks for something similar:
override fun dataFlow() = callbackFlow<ByteArray> {
val characteristicChangedListener = object: ICharacteristicChangedListener {
override fun onCharacteristicChanged(
deviceAddress: String,
characteristic: BluetoothGattCharacteristic,
value: ByteArray
) {
val uuid = characteristic.uuid.toString().uppercase()
trySend(it)
}
}
AndroidBLEDeviceHandler.registerCharacteristicChangedListener(characteristicChangedListener);
awaitClose {
AndroidBLEDeviceHandler.unregisterCharacteristicChangedListener(characteristicChangedListener);
}
}
Then I created a viewmodel for my graph composable and there I collect the flow and put the data in a list:
dataList = mutableListOf()
...
streamEMGJob = viewModelScope.launch {
chartDataManager.dataFlow().collect {
//Process the data
dataList.add(it)
}
}
Not sure if this is the best solution but it works fast enough and does not lose any datapoints