In the last chapter, we briefly introduced anonymous classes. Here, we will learn a little more about them and see how they can help us. When a RadioButton
is part of a RadioGroup,
the visual appearance of them all is coordinated for us. All we need to do is react when any given RadioButton
is pressed. Of course, as with any other button, we need to know when they have been clicked.
A RadioButton
behaves differently to a regular Button
, and simply listening for clicks in onClick
(after implementing OnClickListener
) will not work because RadioButton
is not designed that way.
What we need to do is use another Java feature. We need to implement a class, an anonymous class, for the sole purpose of listening for clicks on the RadioGroup
. The following block of code assumes that we have a reference to a RadioGroup
called radioGroup
. Here is the code:
radioGroup.setOnCheckedChangeListener( new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // Handle clicks here } } );
The preceding code, specifically RadioGroup.OnCheckedChangeListener
from its opening {
to closing }
, is what is known as an anonymous class because it has no name.
The actual class code does not run when onCreate
is called; it simply prepares the class ready to handle any clicks on radioGroup
. We will now discuss this in more detail.
This class is more technically known as an anonymous inner class because it is inside another class. Inner classes can be anonymous or have names. We will see an inner class with a name in Chapter 16, Adapters and Recyclers.
I remember the first time I saw an anonymous class and it almost made me want to hide in a cupboard, but it is not as complex as it might look at first.
What we are doing is adding a listener to radioGroup
, which has very much the same effect as when we implemented the View.OnClickListener
in Chapter 12, The Stack, the Heap, and the Garbage Collector. Only this time, we are declaring and instantiating a listener class, and preparing it to listen to radioGroup
, while simultaneously overriding the required method, which in this case is onCheckedChanged
. This is like the RadioGroup
equivalent of onClick
.
Let's step through it. We call the setOnCheckedChangeListener
method on our radioGroup
as follows:
radioGroup.setOnCheckedChangeListener(
We pass in a new anonymous class, along with the details of its overridden method, as the argument, as follows:
new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // Handle clicks here } }
Finally, we have the closing parenthesis of the method. And, of course, the semi-colon to mark the end of the line. The only reason we present it on multiple lines is to make it more readable. As far as the compiler is concerned, it could all be lumped together:
);
If we use the preceding code to create and instantiate a class that listens for clicks to our RadioGroup
, perhaps in the onCreate
method, it will listen and respond for the entire life of the Activity. All we need to learn now is to handle the clicks in the onCheckedChanged
method that we override.
Notice that one of the parameters of this method that is passed in when the radioGroup
is pressed is int checkedId
. This holds the id
of the currently selected RadioButton.
This is just what we need – almost.
It might be surprising that checkedId
is an int
. Android stores all ids as int
, even though we declare them with alphanumeric characters such as radioButton1
or radioGroup
.
All our human-friendly names are converted to int
when the app is compiled. So, how do we know which int
refers to an id
, such as radioButton1
or radioButton2
and so on?
What we need to do is get a reference to the actual object that the int
is an id for, using the int id,
and then ask the object for its human-friendly id
. We would do so like this:
RadioButton rb = (RadioButton) group.findViewById(checkedId);
Now, we can retrieve the familiar id
that we used for the currently selected RadioButton
, for which we now have a reference stored in rb
, with the getId
method, as follows:
rb.getId();
We could therefore handle RadioButton
clicks by using a switch
block with a case
for each possible RadioButton
that could be pressed, and rb.getId()
as the switch
block's expression.
The following code shows the entire contents of the onCheckedChanged
method we just discussed:
// Get a reference to the RadioButton // that is currently checked RadioButton rb = (RadioButton) group.findViewById(checkedId); // Switch based on the 'friendly' id switch (rb.getId()) { case R.id.radioButton1: // Do something here break; case R.id.radioButton2: // Do something here break; case R.id.radioButton3: // Do something here break; } // End switch block
Seeing this in action in the next working mini-app, where we can press the buttons for real, will make this clearer.
3.17.74.227