A way of using Android Data Binding Library in form pages

Furkan Aşkın
Ozan SuperApp
Published in
3 min readNov 22, 2021

Introduction

In Ozan SuperApp we are using viewState and viewModel for holding the ui states and managing the business logic. Basically viewState has some values and some functions which is associated with the screen. ViewModel has some usecases, livedatas and functions for managing the business. Also, ViewModel holds that viewState and viewModel updates this viewState when needed. In the end, with using data binding we are updating ui if needed. This is the main mechanism of Ozan SuperApp Android side.

But in our new pages we have some form pages and with this mechanism it’s kinda painful because suppose that you have several inputs and for each input you are using TextWatcher then updating some values which is in viewState using viewModel functions like updateName(), updateSurname() etc..

Then i thought that will be an easier way of updating viewState and ui in the same time using data binding. After researching i found a way! Using Two-way data binding will be useful for us but.. How we can use it with viewStates and hold viewState in viewModel?

In this article, i’m gonna try show how we can use Two-way data binding in form pages using Android Data Binding Library.

If you don’t know what is Android Data Binding Library you can start from here :

https://developer.android.com/codelabs/android-databinding

Getting started

Let’s say we have a screen like that, with some fields and includes a continue button. When the fields not empty, button should be enabled and we should reach form values when the button clicked.

First of all we need a viewState for holding these values. The viewState have private backing fields and public fields. (It just kinda encapsulation thing.)

MainFormViewState.kt

Private variables just has initial values. Public variables has custom getter which is annotated with @Bindable annotation, we gonna use them in our xml file. Also they has custom setter, this setter sets the underscored values and also notifies the Data Binding Library using notifyPropertyChanged(fieldId: Int) (For using this function you should extend your data class from BaseObservable).

Now we are ready to go! Let’s create a viewModel which is contains a LiveData and holds this viewState

I also added initData function for setting the initial viewState and submitForm for printing the form values. Now we can create our xml file for activity/fragment

Create a basic xml file for your screen and add your viewState data to xml file. Then design your screen as you wish but make sure while binding the values, use two way binding using @={} notation in xml file.

The @={} notation, which importantly includes the "=" sign, receives data changes to the property and listen to user updates at the same time.

Then you’ll be able to listen/update your variables in the same time. Here is an sample activity :

It calls viewModel.initData() for setting the initial values then observes the form changes with LiveData.

Basically we achieved what we want but we also said button should be enabled when the form is filled. For achieving this actually we don’t need two way binding. We just need a Bindable which is returns button should be enabled or not.

Just add a function to our viewState as shown in the gist file, and bind it to your button’s enabled attribute using data binding.

android:enabled="@{formViewState.continueButtonEnabled}"

Conclusion

With this way we can store our viewState in viewModel with updated values and actually we don’t need any kind of TextWatcher or other functions.

We are able to use some formatters, validators etc. using viewState and BindingAdapters.

I also added form errors mechanism to project, check out the full project from Github.

Thanks for reading! If you enjoyed this story, please click the 👏 button and share it to help others!

If you have any kind of feedback, feel free to connect with me on Twitter.

--

--

Furkan Aşkın
Ozan SuperApp

Android Developer @OzanSuperApp | Speaker @JuniorTalks