StateFlow with One- and TwoWay-DataBinding on Android

There has been a lot of talk in the Android community related to LiveData
being deprecated in favor of StateFlow
. This doesn’t seem to be the case but with the canary release of Android Studio Arctic Fox | 2020.3.1 (before the naming change it would have been 4.3) the last piece of moving away from LiveData
is complete — DataBinding is enabled for StateFlow.
Let’s check out how this works exactly.
From the initial glance the DataBinding
works with StateFlow
with minimum changes.
As the release notes state — For Kotlin apps that use coroutines, you can now use StateFlow
objects as a data binding source to automatically notify the UI about changes in the data. Your data bindings will be lifecycle aware and will only be triggered when the UI is visible on the screen.
To use a StateFlow
object with your binding class, you need to specify a lifecycle owner to define the scope of the StateFlow
object, and in your layout, assign the properties and methods of your ViewModel
component to the corresponding views using binding expressions, as shown in the following basic example:
class ViewModel() {
val username: StateFlow<String>
}//code in xml
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
This looks exactly as we would use LiveData
before — so far so good! 😃
If you’re in a Kotlin app that uses AndroidX, StateFlow
support is automatically included in the functionality of data binding, including the coroutines dependencies. As described in Bind layout views to Architecture Components, data binding works seamlessly with ViewModel
objects.
Now as we have grasped the gist of it, let’s jump into a custom example.
Here is a sample app I have created to test out One-
and TwoWay- Binding
with StateFlow.
The app is loading friends’ names from the data source and also uses TwoWayBinding
to accept user’s input and append it to the names.

The first step is to create the layout file that will have StateFlow
field bound to TextView
with OneWayBinding
and another instance of StateFlow
bound to TextInputEditText
with TwoWayBinding
.
android:text=”@{viewModel.names}”
and android:text=”@={viewModel.addedName}”.
I am also leveraging binding to work with visibility of the TextView
and bind the onClick
action for the Button
.While continuing working with the View layer let’s create a Fragment. The key components to make our app work with binding are creating the binding object and assignig
lifecycleOwner
as you would do while using LiveData
.
//in Fragment's onCreateView
_binding = FragmentFriendsNamesBinding.inflate(inflater, container, false)
_binding!!.lifecycleOwner = viewLifecycleOwner
_binding!!.viewModel = viewModel
return binding.root
Now when the View layer is handled let’s move to the ViewModel implementation.
The ViewModel class will look as following:
One thing to note MutableStateFlow
and StateFlow
require initial value. We can work around it but that does seem inconvenient in a way. For example, I had to introduce an if condition if (addedName.isNullOrEmpty())
in order not to append initial null
value.
Let’s look closer at what is going on in loadFriendsNames
.
As we are using datasource to provide some saved names we are querying repo’s repo.loadFriendsNames()
which looks like this:
class MainRepository {
fun loadFriendsNames(): Flow<String> = flow {
emit(ApiProvider().getNamesFromRemote().joinToString())
}
}
To achieve a desired effect of combining user’s input and the data received I am using a function combine
which provides a way to join values of 2 flows.
Finally, to update UI the line _names.value = it
is the key.
And that’s it, the binding works as expected.😎
For some final thoughts, I was impressed how effortless it was to migrate to StateFlow
with DataBinding
. I can definitively say so far so good. I will for sure consider using StateFlow
in my future projects to maintain this nice eco system with Kotlin coroutines. The absence of DataBinding
support was a deal breaker for me in the past.
🙌 To check the full project go to https://github.com/AnastasiaRainMaker/StateFlow_DataBinding_Example
🙌 To find out more about advanced DataBinding check https://proandroiddev.com/advanced-data-binding-binding-to-livedata-one-and-two-way-binding-dae1cd68530f
🙌 To read official docs go to https://developer.android.com/kotlin/flow/stateflow-and-sharedflow
No comments:
Post a Comment