Forms in Epoxy

Yusuf Gökmen Arısoy
Delivery Hero Tech Hub
4 min readNov 23, 2021
Photo by Dayne Topkin on Unsplash

Epoxy is a great Android library but there aren’t many resources to learn about it, especially when it comes to forms (EditTexts).

Most of our app is written with Epoxy but not the pages with forms because there were concerns about its usability. So I wanted to make research about using EditText and creating forms in Epoxy and also make a sample application to see its benefits and drawbacks.

Epoxy

RecyclerView is a great and powerful component for listing but when writing applications with multiple complex screens there is a lot of code that needs to be written over and over again. So Airbnb created the Epoxy library to make it even more useful and powerful.

Shortly we are creating our views in layout files and then writing EpoxyModel classes for the views, every model is a view type for RecyclerView. That’s it, now we can display them in any recycler view that we want in our application. Also, it has its own diffing so we don’t need to deal with it.

Epoxy Model

We can pass data to models and use them with our views on bind. We also can pass methods to be triggered from the model or TextWatcher to observe changes in the model from fragments or activity. For to declare the fields to pass the model we mark them with ‘’EpoxyAttribute’’ annotation. For performance, we need to remove listeners or set them null on unbinding, also whenever their hash changes properties rebound so for better performance we use the DoNotHash option (additional information in the link) on listeners.

Epoxy generates models of our views that can be used in controllers. Generated classes have an underscore suffix, for the above example generated models name’ll be “TextInputEpoxyModel_()”. But if you’re using Kotlin in your project, Epoxy generates extension functions for your models and it’s easier to use.

There is a little bug happening because of a new model’s getting build with every update and text watchers subscribing to all of them, so to prevent this I wrote a custom editText named ExtendedTextInputEditText, like TabLayouts TabSelectedListener it has a subscriber list and it controls if it already contains watcher before adding. And also added some methods like “setInputText()” to make it more useful. I may add more features and create a helper library to use with forms in Epoxy in the future.

Epoxy Controller

Both usages of models in the controller can be seen in the above example. Generated extension functions will be named without the ‘’EpoxyModel’’ part. Models will be displayed in the order in which they are written. Because we’re using a RecyclerView we need to notify our view with every data update and corresponding to notify methods of RecyclerView there are “requestBuild” methods.

Using EditText

Saving the text value of editText is the way to use it because it’ll be lost if we don’t bind it. We’re going to register a text watcher on the model, save the data to a field in the view model and rebuild the models depending on that field. Models will be rebuilt whenever the field is updated but thanks to diffing, only the models with changes will rebuild.

Before binding a text to EditText we need to control to see if the text is different from views text (setInputText method of custom editText) to prevent setting on every build for different changes. Also delayed build is recommended to avoid rebuilding with every input.

We’re already holding our text properties (email and password for example) in the view model, so getting and passing the text values of editTexts with onClicked isn’t needed, can use them directly. Also with something like a stateful view model controlling the data is so much easier, I wrote the sample app with this logic.

In Fragment

We’re watching the changes in models from fragments and setting the fields on text changed, the controller will rebuild with delay whenever a data is set. Also, we’re calling the login method without passing any values.

In ViewModel

There are two fields to store our values in the view model and we’re setting them with methods. Cause we already have the latest values in our view model we can control them in the “loginControl()” method and take action depending on them.

This is shortly how to use EditText and create forms with the Epoxy library. More examples and usages, full and extended versions of sample codes, and also stateful view model and custom classes can be found in my Github repository epoxy-advanced. Hope it helps!

--

--