Custom Listeners In Android

Listeners are a staple of Android development. They are a very popular way of creating asynchronous callbacks. Listeners are generally used to implement the code that runs when an event occurs.
A common usage of listeners that you likely have come across, if you’re a bit experienced in Android development, is the built-in onClickListener of a button. We usually set the onClickListener on a button, with the code that should run when the button is clicked, which is the event in this case. In Java, it usually looks like this:
Button button = findViewById(R.id.example); button.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { //Do some work here } });
But besides what I described above, we can create our custom listeners with callbacks attached to events that are fired from certain areas of our code.
But why?

Here are some cases where we might need to create a custom listener:
When we need to emit an event up from a fragment to an activity
When we need to emit an event up from within an adapter to an activity or fragment
In general, a listener is useful when you have a “child object” and a “parent object” or handler, where a parent object is an object that creates a new instance of the child object. And we have some work that needs to be done in the parent object, but also needs to be done only when a certain event occurs in the child object. So we have to find a way to communicate the fact that the event in question has occurred in the child object, to the parent object.
So how do we create a custom listener?
- First, define an interface in the child object (adapter, fragment, POJO). Then define the events that will be fired up to the parent. These events are represented by methods in the interface. An example of how this may look like in Java is:
public interface CustomListener{
void onDataReady(Data data);
void onSubmitForm();
}
In the above example, onDataReady(Data data) and onSubmitForm() are method signatures/callbacks that represent events that may occur in the child object.
2. Next, set up a listener variable to store a particular implementation of the callbacks in our interface. The implementation of the callbacks will be defined by the parent object. So inside the child class, you can make the variable as well as a public setter method which allows the listener callbacks to be defined from the parent, like so:
private CustomListener mListener;
public void setCustomListener(CustomListener listener){ mListener = listener; }
You don’t have to use a setter method, as there are several methods to pass the listener callback implementation into the child object, such as passing it through the constructor or passing it in via a lifecycle event(such as the onAttach() event of a fragment when dealing with activity/fragment communication).
3. Now that we’ve created the listener variable, we can implement the interface on the parent class, override the methods, and put in our implementation of those methods, then set the listener implementation(which is our parent class that implements the interface), on the child object.
public class Parent implements Child.CustomListener{
//Some code
...
@Override public void onDataReady(Data data){ //some fancy implementation }
public void onSubmitForm(){ //code we want to run when this event occurs }
childObject.setCustomListener(this);
}
The above is a very common way of creating an implementation of the listener in the parent class. Another way of doing the same thing we did above is to create an instance of the custom listener inside the parent class (instead of making the parent class itself implement the interface) and setting that implementation as the custom listener for our child object, like so:
Child childObject = new Child();
Child.CustomListener listener = new Child.CustomListener(){ @Override public void onDataReady(Data data){ //some fancy implementation }
public void onSubmitForm(){ //code we want to run when this event occurs }
}
childObject.setCustomListener(listener);

Just kidding, almost there though.
4. Now the child object can fire up events to the parent using the listener, when they happen, and pass along data if any, to the parent object. For example, in the child object, this can look like:
//The event "onDataReady" has occurred in the child object and we //fire up the event to the parent using the listener
public void OnSuccess(Response response){
Data data = response.getData;
listener.onDataReady(data);
}
And that’s it, we are done setting up the custom listener! I hope you’re able to start making and using your custom listeners if you haven’t already. Or at least have gained a better understanding of them.

