Updated 22/04/19 to include Kotlin code samples and use latest version of Dagger Android.
The typical method of implementing a binding adapter using the Android Data Binding Library is to create a static method using the @BindingAdapter
annotation, such as this commonly quoted example:
This has been widely documented and discussed on the Internet already and fits many use cases.
But, what if your adapter has external dependancies, or you don't want to define it in a global scope?
Binding adapters don't have to be static...
Creating a non-static binding adapter
This functionality of the data binding library is completely lacking from the official documentation, but there are a few examples floating around on Stack Overflow.
Let's create a simple adapter similar to the above example:
Rather than creating a new Picasso instance each time, Picasso is now passed to the constructor as a dependancy. For Picasso in particular this could be useful if you want to use the builder to create a custom instance and avoid having multiple instances of Picasso.
When creating a binding adapter in this way, the data binding library generates the DataBindingComponent
interface[1]. This interface contains a getter for each separate adapter defined:
Looking at the DataBindingUtil
docs we can see there are a number of methods that utilise the DataBindingComponent
, such as setDefaultComponent
, inflate
and setContentView
(more on this later).
One way to use the adapter is to create a concrete implementation of the DataBindingComponent
, this could be done manually or with Dagger 2 to also utilise the graph to provide any external dependancies.
Building the DataBindingComponent with Dagger
It should be possible to create either a component or a sub-component, in this example I chose to use a component as it's not really necessary to expose the entire graph to the binding adapters.
A component requires a scope so I created @DataBinding
for this.
Here's the module which provides the ImageBindingAdapter
:
And here's the component:
In order to satisfy the dependancy for Picasso in BindingModule
, it also has to be exposed by the AppComponent
(this step would not be required if using a sub-component):
Dagger automatically implements all the methods from the DataBindingComponent
. Here's a snippet of what gets generated under the hood:
Using the component
The easiest way to use the new component is to create it in the Application
class, particularly if using Android injection in Dagger 2.10+ as you no longer need to expose the main component to activities. It's now a standard Dagger component so it simply needs to be built in the usual way and then passed to DataBindingUtil.setDefaultComponent()
.
Here's a sample Application
:
This of course is effectively still in the global scope, the component can also be used with a specific layout:
In an Activity:
In a Fragment: