Slackbot
08/30/2021, 12:43 AMdarkmoon_uk
08/30/2021, 1:08 AMState
objects to their Views. Somtimes there are situations of truly sealed
state where this is the only approach that makes sense, but I try to have as much destructuring as possible already done by the ViewModel. Reasons for this are that I believe in general the View layer should be as thin as possible: if you come to write a different View layer for another platform (say, Web) then you want to be rewriting as little code as possible. The ViewModel should spell out the View as explicitly as possible.darkmoon_uk
08/30/2021, 1:11 AMState
destructure.Lilly
08/30/2021, 1:12 AMdarkmoon_uk
08/30/2021, 1:12 AMFlows
you also keep changes to the View more granular, which can lead to better performance overall.darkmoon_uk
08/30/2021, 1:13 AMdarkmoon_uk
08/30/2021, 1:13 AMDeviceViewModel
that gets instanced for every device in your listdarkmoon_uk
08/30/2021, 1:14 AMdarkmoon_uk
08/30/2021, 1:14 AMDeviceViewModel
can expose a StateFlow
for each of the changing data.darkmoon_uk
08/30/2021, 1:14 AMLilly
08/30/2021, 1:18 AMyou also keep changes to the View more granular, which can lead to better performance overallI had exactly this granularity in mind when I was asking for the right approach. If I have just one State object, the problem is that there have to be hust one field that changes quite often to trigger a new object creation
darkmoon_uk
08/30/2021, 1:19 AMdarkmoon_uk
08/30/2021, 1:19 AMStateFlow
for the actual fields of your domain Model object.darkmoon_uk
08/30/2021, 1:20 AMdata class DeviceModel(
val deviceName: String,
val deviceAddress: String,
val rssiFlow: StateFlow<Int>
)
darkmoon_uk
08/30/2021, 1:22 AMdeviceAddress
as a key, then update the rssiFlow
with the newly updated value.darkmoon_uk
08/30/2021, 1:22 AMval rssiDescriptionFlow : StateFlow<String> = model.rssiFlow.map { rssi -> "${rssi} db" }.stateIn(scope, Eagerly, "- db")
Lilly
08/30/2021, 1:24 AMdarkmoon_uk
08/30/2021, 1:25 AMval deviceViewModel.rssiDescriptionFlow.collectAsState()
darkmoon_uk
08/30/2021, 1:25 AMList<DeviceViewModel>
- where each of those DeviceViewModel
's prepares the presentation values for a DeviceModel
that it, in turn, holdsdarkmoon_uk
08/30/2021, 1:26 AMdarkmoon_uk
08/30/2021, 1:26 AMdarkmoon_uk
08/30/2021, 1:27 AMLilly
08/30/2021, 1:31 AMdarkmoon_uk
08/30/2021, 1:35 AMRafiul Islam
08/30/2021, 5:01 AMLilly
08/30/2021, 10:07 AM// Every time a new BluetoothDevice is discovered, it's wrapped into this class.
// It happens quite frequently, that the same device is discovered multiple times but the rssi changes
data class BluetoothDeviceWrapper(val device: BluetoothDevice, val rssi: Int) {
override fun equals(other: Any?): Boolean {
if (other is BluetoothDeviceWrapper) {
return this.device.address == other.device.address
}
return false
}
}
val isScanning = mutableStateOf(false)
val devices = mutableStateListOf<BluetoothDeviceWrapper>()
To reflect rssi changes when an equal device arrives, I remove the existing device from the devices list and re-add the new device.
But I don't like to expose such a type that is so tied to android. Instead I want to expose a DeviceModel:
data class DeviceModel(
val deviceName: String,
val deviceAddress: String,
VAR rssi: Int
)
Here I have multiple questions:
I have seen, that many users expose just one big state object to the UI, so I'm wondering if I should do the same instead of exposing isScanning and devices seperately?
This might look like this:
data class ScannerState(
VAR isScanning: Boolean,
val devices: MutableList<DeviceModel>
)
But then I'm wondering if I can handle the duplicates like stated in the comment of the first code snippet above in a more elgant way than removing and re-adding the devices. Is it possible to update the rssi field so that compose is notified about this change and recompose? Same question for the isScanning field. When I make DeviceModel or ScannerState immutable this implies that I have to create a new object for every change of isScanning isn't that a problem or bad practise to create a new object so often? The frequency how often ScannerState is created can be reduced when I handle isScanning and devices separately, so I'm not sure whats the right approach. Another problem AFAIK is the MutableList. I doubt compose can handle mutable lists so I'm forced to create a new immutable list for every new discovered device.
@Rafiul Islam
@JulianKLilly
08/30/2021, 10:08 AM