I've recently got into Android and have been looking at examples about Inner classes but don't really understand what the use of them is. They are used often when making listeners and when making a full class is unnecessary right? Maybe someone can explain it to me in laymans terms, also what would the alternative to using an inner anonymous class in this situation be?
This code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
Thanks
One alternative pattern is to make the container class itself a listener.
public class MyClass implements View.OnClickListener {
#Override
public void onClick(View v) {
// Do something when button is clicked
}
public void initOrSomething() {
button.setOnClickListener(this);
}
}
However you may run into trouble if you have more than one button that needs to behave differently.
Another way is to have different listener classes for each button
public class Button1Listener implements View.OnClickListener {
#Override
public void onClick(View v) {
// Do something when button1 is clicked
}
}
public class Button2Listener implements View.OnClickListener {
#Override
public void onClick(View v) {
// Do something when button2 is clicked
}
}
button1.setOnClickListener(new Button1Listener());
button2.setOnClickListener(new Button2Listener());
Anonymous inner classes are just a more compact representation of the second pattern.
EDIT: Variations of both patterns are possible, where contents of the View object are examined to determine which button was clicked or constructor arguments are passed to the listener class to change listener behavior etc.
They are used often when making listeners and when making a full class is unnecessary right?
Listeners in Android, or other interfaces in other situations. But in essence, that's about it.
what would the alternative to using an inner anonymous class in this situation be?
It would be to create a class which implements this interface and submit it as an argument. For instance:
public class MyListener
implements View.OnClickListener
{
// implement onClick(), etc etc
}
// In code:
button.setOnClickListener(new MyListener(...));
That's quite simple: What you are doing is just creating a class. For the JVM (or dalvik in this case), it doesn't matter if the class is it's own compilation unit (a file), an inner class or an anonymous class(*). So you have three equally valid options:
Option 1 Your example:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
Option 2 named inner class:
public MyActivity extends Activity {
static class MyListener implements View.OnClickListener {
#Override
public void onClick(View v) {
// do something
}
}
....
button.setOnClickListener(new MyListener());
}
and Option 3 Different Files:
File MyListener.java
public class MyListener implements View.OnClickListener {
#Override
public void onClick(View v) {
// do something
}
}
File MyActivity.java
import MyListener.java
public MyActivity extends Activity {
....
button.setOnClickListener(new MyListener());
}
Which of these options you use is completely subjective - Depending on your needs and usage, one or the other makes more sense.
However, generally in UI listeners, you don't want to have any logic that is disjunct from the logic of the Activity you are programming. Hence you use the anonymous class, because all the code stays in one place and makes it decently readable.
Related
I have trouble understanding this code. I get that findViewById will get the button widget and then it'll cast it. Then, it's going to use the button to call the setOnClickListener method. However, I don't know what is that argument being passed into the setOnClickListener and I have never seen code like that before. How is it that it creates a new object but is able to create a method of its own within another method's argument? Would be great if someone could explain that. Also, what type of object is the setOnClickListener method taking in?
btn = (Button)findViewById(R.id.firstButton);
btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
tv.setText(months[rand.nextInt(12)]);
tv.setTextColor(Color.rgb(rand.nextInt(255)+1, rand.nextInt(255)+1, rand.nextInt(255)+1));
}
});
It works like this. View.OnClickListenere is defined -
public interface OnClickListener {
void onClick(View v);
}
As far as we know you cannot instantiate an object OnClickListener, as it doesn't have a method implemented. So there are two ways you can go by - you can implement this interface which will override onClick method like this:
public class MyListener implements View.OnClickListener {
#Override
public void onClick (View v) {
// your code here;
}
}
But it's tedious to do it each time as you want to set a click listener. So in order to avoid this you can provide the implementation for the method on spot, just like in an example you gave.
setOnClickListener takes View.OnClickListener as its parameter.
This is the best way to implement Onclicklistener for many buttons in a row
implement View.onclicklistener.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
This is a button in the MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_submit = (Button) findViewById(R.id.submit);
bt_submit.setOnClickListener(this);
}
This is an override method
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.submit:
//action
break;
case R.id.secondbutton:
//action
break;
}
}
That what manual says about setOnClickListener method is:
public void setOnClickListener (View.OnClickListener l)
Added in API level 1 Register a callback to be invoked when this view
is clicked. If this view is not clickable, it becomes clickable.
Parameters
l View.OnClickListener: The callback that will run
And normally you have to use it like this
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
Take a look at this lesson as well Building a Simple Calculator using Android Studio.
its an implementation of anonymouse class object creation to give ease of writing less code and to save time
It works by same principle of anonymous inner class where we can instantiate an interface without actually defining a class :
Ref: https://www.geeksforgeeks.org/anonymous-inner-class-java/
I'm doing some Android development and I have an object, which doing a specific task. When that task is done I need to inform my main method (Main Activity), which is constantly running, that the process has been finished and pass some information about it.
This may sound a bit unclear, so I'll give you an example:
Take a look at the setOnClickListener() method in Android:
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
//This method is called on click
#Override
public void onClick(View v) {
//The View is passed in an anonymous inner class
}
});
It waits for a button to be clicked and calls the onClick(View v) method. I am seeking to achieve the same code structure. How to do this?
You mentioned "process". If you are truly doing something in a different process, then you need to look at interprocess communications (IPC). Otherwise, you can use an interface:
Create a class called MyListener:
public interface MyListener {
void onComplete();
}
In your class that will notify your activity:
MyListener myListener;
public void setMyListener(MyListener myListener){
this.myListener = myListener;
}
Then, when you are ready to notify your main activity, call this line:
myListener.onComplete();
Last, in your MainActivity implement MyListener:
public class MyListener extends Activity implements MyListener {
///other stuff
#Override
public void onComplete(){
// here you are notified when onComplete it called
}
}
Hope this helps. Cheers.
This is exactly Listener pattern that you use with views in android. What you want to do is declare an interface in your class that's doing the job, and pass an instance of this interface. Raw example:
TaskDoer.java:
public class TaskDoer {
public interface OnTaskDoneListener {
void onDone(Data data);
}
public void doTask(OnTaskDoneListener listener) {
// do task...
listener.onDone(data);
}
}
Activity:
public void doTaskAndGetResult() {
new TaskDoer().doTask(new TaskDoer.OnTaskDoneListener() {
public void onDone(Data data) {
// do something
}
}
}
I have a good background in C, and now I am writing code for android/java.
What I fail to understand that why function definition of a handler function is done inside another function. Code becomes so messy and hard to maintain and understand( from a C programmer POV).
So I have this code
final Button btnOpenPopup = (Button)findViewById(R.id.menuButton);
btnOpenPopup.setOnClickListener(new
Button.OnClickListener()
{...}
Is it possible to have a function
myButtonClickListner() {} defined in the class and btnOpenPopup.setOnClickListener((SomeCast)myButtonClickListner
I think there has to be a way, But I am not able to find it..
Please comment.
Well, there are two ways to do this:
1- Have the containing class implement the OnClickListener interface. For example:
public class MainActivity extends Activity implements OnClickListener{
//...
public void onCreate(Bundle savedState){
//...
final Button btnOpenPopup = (Button)findViewById(R.id.menuButton);
btnOpenPopup.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.button1:
//
break;
}
}
2- The second method is the one described by Selvin in his comment: creating a separate class, which implements the OnClickListener interface, and instantiate it in your onCreate(). So, assuming that you have a myButtonListener class in its own myButtonListener.java file, you can simply do:
final Button btnOpenPopup = (Button)findViewById(R.id.menuButton);
btnOpenPopup.setOnClickListener(new myButtonListener);
The idea behind using
final Button btnOpenPopup = (Button)findViewById(R.id.menuButton);
btnOpenPopup.setOnClickListener(new
Button.OnClickListener()
{...}
such coding style is that the object and its implementation stays together at one place.
in above code we have used anonymous innerclass.
If you are not comfortable with such implementation then there is also another way of doing this.
In your activity, implement onClickListener like below:
public class MainActivity extends Activity implements OnClickListener{
Button btnOk;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//find id of your button
btnOk = (Button) findViewById(R.id.btnOk);
//Registering it for click listener
btnOk.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnOk:
System.out.println("OK button is clicked");
break;
case 2:
//some other controls
break;
default:
break;
}
}
}
Implement View.OnClickListener on your class and override its onClick method. That would make the code somewhat cleaner.
But first i recommend you to have proper knowledge of OOP and Java.
You just need to implement the OnClickListener interface and override the onCLick method. And on your onCLick() method you just need to add a filter for the corresponding View.
public void onClick(View arg0){
if(arg0 == myButton){
//do stuff when myButton is click
}else if(arg0 == myOtherButton){
//do stuff when myOtherButton is click
}
}
- What you have encountered is know as Anonymous Inner Class.
Anonymous Inner Class:
It has no name.
It must implements or extends one and only one Interface or Class respectively.
- This is just a way of coding where you keeping the functionality of that view or component attached visually.
The another way you can do that is by doing the following:
- Implement the specific Interface that has the call-back method.
public class MainActivity implements OnItemClickListener{
private Button buttonClick;
....
....
onCreate(Bundle saveInstance){
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
buttonClick = (Button)findViewById(R.id.button_click);
buttonClick.setOnClickListener(this);
...
...
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_click:
// -------- Do you function here
break;
}
}
}
I've read many threads on how to create and handle Button clicks using onClickListener. However, I couldn't find anything that solved this problem.
I have a class myActivity and I would like to create a second class myExtendedActivity which extends myActivity by adding some extra functionality.
The class myActivity contains a lot of code which, for maintainability reasons, I don't want to duplicate. myExtendedActivity should behave exactly as myActivity with some extra function.
In particular in the onCreate method in myActivity I have the following code that add an onClickListener to my_button. The extended activity should just append a call to myExtraMethod.
myButton = (Button)findViewById(R.id.my_button);
myButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
[...] //a lot of code here
myExtraMethod();
}
});
Note that myExtraMethod simply broadcasts an Intent and it is not affected by any other part of the code in the Listener.
What I would like to do is to extend the OnClickListener in myExtendedActivity so that it first executes exactly the code written for myActivity and than myExtraMethod defined in myExtendedActivity.
I don't want to modify myActivity which should be completely unaware if myExtendedActivity is included in the project or not.
Thank you very much
Completely without modifying myActivity is barely possible.
You could use something like this in MyActivity (Some variant of the Template method pattern):
onCreate() {
myButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
myMethod();
}
});
}
protected void myMethod() {
[...] //a lot of code here
}
And then in MyExtendedActivty:
#Override
protected void myMethod() {
super.myMethod();
myExtraMethod();
}
If I understood your question right, the solution might be something like this:
In your layout for button you define the onClickListener from xml:
<Button
android:id="#+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="handleButtonClick"
/>
Then, in MyActivity you implement method:
public void handleClick(View view) {
}
And in MyExtendedActivity you override it:
public class MyExtendedActivity extends MyActivity {
#Override
public void handleClick(View view) {
super.handleClick(view);
//your code goes here
}
}
Without modifying myActivity, you can't because you're instantiating an anonymous class, and the subclass has no way to "hook in" to that anonymous class.
If you can modify myActivity, then you could make the anonymous class from myButton.setOnClickListener(...) a static class, and in your subclass extend the listener class calling super.onClick(v), followed by the functionality you expect.
Then add a method to get the correct listener
myButton.setOnClickListener(createMyButtonsListener())
that you can then override in the subclass providing the extended version.
Alternatively, add a method that can be overriden in a subclass (i.e. myExtraMethod()). that is called within your anonymous class.
Is View.OnClickListener() a function or interface? When we try to set a onclicklistener() method in android, we use new View.OnClickListener() and it bugs me there cuz as far as I know,
we don't need to initialize an object of class containing static method inorder to use those methods. Why we do this?
When we use implements inorder to implement an interface, we don't call the static methods of the interface.
So can some one tell me why do we do:
new View.OnClickListener(), for using onclick() method?
Why do we use () with View.OnClickListener if it is an interface?
Thanks for your reply..
I'm not sure I understand what you are writing about static methods. View.OnClickListener is an interface: http://developer.android.com/reference/android/view/View.OnClickListener.html
To set a click listener on a view, you pass an instance implementing the OnClickListerner interface: http://developer.android.com/reference/android/view/View.html#setOnClickListener(android.view.View.OnClickListener)
The most common way to do this in android is to define an anonymous inner class (http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html) that implements OnClickListener like
myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Handle view click here
}
});
The code above both defines an anonymous inner class and creates an instance of it. It is equivalent to first defining a class implementing View.OnClickListener (if defined in the same class)
class MyOnClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
// Handle view click here
}
}
And later using this
MyOnClickListener listener = new MyOnClickListener();
myView.setOnClickListener(listener);
Sample Code,
Internally it works something like this,
public class MyView{
public stinterface MyInterface{
public void myOnClick(View view);
}
}
public class MyButton{
View view;
public void setOnClicker(MyInterface onClicker) {
onClicker.myOnClick(view);
}
}
public class MyExample{
public void method(){
MyButton myButton = new MyButton();
myButton.setOnClicker(new MyInterface() {
#Override
public void myOnClick(View view) {
}
});
}
}