- Hidden Bits by Antonio Leiva
- Posts
- Can I collect a StateFlow from Java code?
Can I collect a StateFlow from Java code?
The nightmares of legacy code
The other day, a student of one of my courses asked me one question that left me thinking:
“Can I collect a StateFlow
from Java?”
Oh my! Why would you need this? It's the first thing I thought.
But it turns out that there are a lot of situations (especially in an old App originally written in Java) where you could find that need.
Imagine that you have a ViewModel written in Kotlin but, for whatever reason, you still can't convert your Activity or Fragment to our beloved language.
So what can you do? Calling a suspending function like collect()
from Java can be a nightmare, so I would discard it.
But then I thought of an alternative…
There's an extension function for Kotlin that allows to convert a StateFlow
into a LiveData
. And LiveData
works perfectly in Java.
So what can we do? My first approach was to modify the ViewModel so that it exposes a LiveData
instead of a StateFlow
for its state.
But let's be honest, in most situation this may not be a solution.
It's quite possible that the StateFlow
is being consumed in other parts of the App. So doing this would break some code somewhere.
The ideal situation would be to encapsulate the “hack” in the class that wants to collect it, so the rest of the code is not affected.
Guess what? I already mentioned the solution. What forbids us calling the extension function from Java? Nothing!
So you can just convert the StateFlow into a LiveData right into the Fragment.
Let the magic happen
To do that, first you need the add a dependency that, ironically, is meant to be used in Kotlin code (life is ironic sometimes):
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
And then, you can use the extension function asLiveData()
from pure Java code:
LiveData<DetailViewModel.UiState> liveData = asLiveData(viewModel.getState());
liveData.observe(getViewLifecycleOwner(), state -> {
// Update UI
});
And that's it! Now you have the conversion hidden in the place where you need it, and nobody else needs to know.
I also must say that I don't know if there a better alternative, please answer back if you find another way.
I admit I didn't enjoy writing Java code again 😅
Since most of you chose a frequency one article per week, I'm setting the day to Sundays. Let's see how it goes there. Thanks!
Reply