1 — Intro
Sometimes we use the same UI element many times in our project. A smart way to avoid repeating the same code over and over is to create a CustomView or a fragment to encapsulate the desired behavior.
But, sometimes, creating custom views or managing fragments lifecycle may be over complicated. You usually end up with a custom view with a lot of boiler plate code or nested fragments with complex life cycles. A really simple way to deal with this problem is to use data binding to create little pieces of reusable UI. We only need to write code in the XML and the communication with the component is made by the bindings.
The code for this article can be found in this repository: https://github.com/leandroBorgesFerreira/DataBindingComponentSample
2 — The project
We are going to build a simple number keyboard to illustrate the use of data binding for creating UI components. This one:
Nothing really special here. The interesting part is HOW we do it.
3 — Let's create XML of the keyboard
You can construct the keyboard with the code in the next gist. It has a lot of lines, but it's just the some information over and over. I will explain the important part after the gist, so don't waste too much time on this piece code.
The name of this xml is number_keyboard, this will be important later.
4 — We need to communicate with the XML
The communication parts (the important parts in the XML) are this:
We are importing the Actions so we can use some constants that we are going to define. We also need a listener for the button clicks. This is our keyListener, it is a variable in our XML and we are going to instantiate this when we finally use our library.
So we have a listener that will listen for the clicks in all the buttons. All we have to do now is to define the interface for this listener and our library is complete. No need for concrete classes!
So we define our listener:
To make this library able to erase the text, we need to define a Char that ask for erase instead of writing:
So this is our library. Pretty easy, right?
So now all we need to use this library in a project. Let's do that.
5 — Let's use our library
So it is time to use the library. We didn't instantiate our keyListener, do you remember that? So we need to add the key listener in the XML of our activity. It will inside our viewModel, the class that coordinates our activity.
Our keyboard is the code:
We use our library as a simple include. That's the magic: we don't need a fragment with a complex life cycle or a complicated custom view, all we have is a simple include.
For the communication we use a listener in our ViewModel. The ViewModel will be defined in our XML. Let's take a look:
We are defining our ViewModel. It has a testObservable that will receive the text inserted in the EditText. Please note that I am using two way data binding. The ViewModel also it has our listener.
So let's create our ViewModel
6 — The ViewModel
To coordinate our XML, we just need a simple ViewModel.
The onKeyClick is implementing the OnKeyClick interface that we defined in our library, that's how our communication works. The method receiveText() receives the character provided by Keyboard then evaluates if the command is to erase or to write and performs the right action.
7 — Finally, the bind
Create the activity and create the bind, simple as that:
And that's it.
8 — Is this approach really better?
My first try was to create a fragment to solve the keyboard problem. It seamed like a good solution and, at first, it worked just fine. But then I had to use the keyboard inside an another fragment in a ViewPager. This created some annoying problems with the life cycle of nested fragments for a very simple screen… nested fragments are just a nightmare o.O
So I decided to make a component using data binding. It made the project a lot simpler and my favorite part: No concrete classes! Just a simple interface for a listener. I used the same approach for some other views, and it worked fine. This is a scope of problem where data binding really shines!
But please remember that this is no silver bullet. If the problem you are trying to solve involves complex animations, the lack of Java/Kotlin code can make it impossible. Evaluate your needs before deciding to make a component with a fragment, custom view or data binding.
If you enjoyed reading this, please click the heart icon below. This will help to share the story with others. If you would like to see more content like this one, follow me.