Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Android

onClickListener problem.

Hi guys, i am always scared by this code which is used very often... can someone explain this completely in a nice way to me...

What are the parameters of the method and then there is a method within a method... its all confusing...

mGetAnswerButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub

            }
        });

1 Answer

Justin Horner
STAFF
Justin Horner
Treehouse Guest Teacher

Hello Divyansh,

I'll certainly do my best to explain what's going on.

Firstly, the button needs a callback, some code to call when the button gets clicked. The way we set that callback is with the setOnClickListener.

Looking at the documentation for setOnClickListener, we can see that it takes an implementer View.OnClickListener as a parameter.

[Documentation - setOnClickListener](http://developer.android.com/reference/android/view/View.html#setOnClickListener(android.view.View.OnClickListener)

So what is View.OnClickListener? From the documentation it an Interface definition for a callback to be invoked when a view is clicked.

Documentation - View.OnClickListener

So we know we need to pass an instance of an object that implements the View.OnClickListener interface. If the class you're working in doesn't implement View.OnClickListener than the common way to accomplish this is to create an anonymous inner class.

Now here is where the magic happens. Let's look at the button click example again.

mGetAnswerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub

        }
    });

Here's the breakdown of what's happening here. By creating a new View.OnClickListener() and defining the code block, you are essentially creating an anonymous inner class that implements View.OnClickListener.

This is the same net result of creating a new Java class that implements View.OnClickListener, creating an instance of it and passing it to the setOnClickListener method.

I hope this helps. If you still have questions I'll do my best to explain further.

Thanks for answering Justin! I have got some doubts...

  1. the button 'mGetAnswerButton' is itself a view... and we are calling setOnClickListener on it, then why does it need a new View as a parameter? is this just a convention?

  2. if i don't create the 'anonymous inner class' and rather create it separately in my code, override the onClick method and then call its instance as my parameter in my setOnClickListener method instead, it should work... isn't it? it's just that the above code looks too ugly to look at.

Justin Horner
Justin Horner
Treehouse Guest Teacher

You're welcome! About the other questions...

  1. Remember that setOnClickListener does not necessarily take a view as a parameter. it takes a class that implements the View.OnClickListener interface. This class being passed in implements the interface which means when the button is clicked, the framework can trust that an onClick method exists on the object is passed to it as the callback.

  2. Yes, in fact there are several approaches to setting button click listeners. Check out the documentation for Button. In the class overview, second example you'll see you can also define them in xml and simply have a matching method in your activity that has a View as a parameter. The view parameter is simply a way to get the sender, or the button clicked, to the callback.

Another approach would be to make your Activity class implement View.OnClickListener and use a switch on the view id to find which button was clicked like this.

  public class MainActivity extends Activity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ((Button)findViewById(R.id.buttonA)).setOnClickListener(this);
        ((Button)findViewById(R.id.buttonB)).setOnClickListener(this);
    } 

    @Override
    public void onClick(View v) 
        {
                switch (v.getId()) { 
                {
            case R.id.buttonA:
                // TODO: Work here for button A
                break;
            case R.id.buttonB:
                // TODO: Work here for button B
                break;
            default:
                break;
            }   
    }
  }

So you can see in this example when calling setOnClickListener we're passing 'this' as the View.OnClickListener because our Activity class implements the View.OnClickListener interface.

I hope this helps.

Thanks Justin!