Is it possible to observe in a viewmodel the value...
# android
p
Is it possible to observe in a viewmodel the value of a variable stored in a singleton? maybe can be observed with a flow? how can this be done?
Copy code
object customSingleton {
    var customVar = "Hello World"
}
How can that be observed in a viewmodel?
m
A flow is probably the best solution. But other options 1. poll for changes 2. RxJava 3. A callback that you can register and unregister. And many more. But you either need to poll or the object needs to notify anyone interested when it changes.
p
can you show me how to achieve it with flow?
m
Look up how to use
StateFlow
. But general way, would be to have a private
MutableStateFlow
, make the
customVar
getter and setter use the value from
MutableStateFlow
and then expose another property of type
StateFlow
that can be collected. Then in the view model, collect the state flow in a job launched from the view model's scope.
p
it's really hard for me to use flows
can't get the point
Copy code
val currentScreenId = MutableStateFlow<Int>(CustomSingleton.customVar)

val currentScreenIdState: StateFlow<Int> = currentScreenId.stateIn(
    viewModelScope,
    SharingStarted.WhileSubscribed(5_000),
    CustomSingleton.customVar
)
Is that code correct? should I put the init value
CustomSingleton.customVar
in these two places? When I update the variable on the singleton will the composables listeing for this stateflow be recreated?
well, something is not going well, because, when I update the variable (
CustomSingleton.customVar = 1
), the composable is not being recomposed
I'm getting the variable this way in the composable:
Copy code
val currentSectionId by viewModel.currentScreenIdState.collectAsStateWithLifecycle()
m
The flow goes in
CustomSingleton
.
Copy code
object CustomSingleton {
    private val _customVarFlow = MutableStateFlow("Hello World")
    val customVarFlow = _customVarFlow.asStateFlow()
    var customVar: String
        get() = _customVarFlow.value
        set(value) {
            _customVarFlow.value = value
        }
}

class MyViewModel: ViewModel() {
    init {
        viewModelScope.launch { 
            CustomSingleton.customVarFlow.collect { currentVal ->
                // do something
            }
        }
    }
}
p
using collect in the vm instead of collectasstatewithlifecycle in the composable is a good idea?
m
collectAsStateWithLifecycle
is an option. You asked about the view model listening to it. So it all depends on what you are doing with it.