syntax issue regarding to setOnClickListener? - android

May anyone explain to me this bit of code?
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
startActivity(intent);
}
});
In this case, MainActivity and DetailActivity are two classes I have created.
I am kind of confused,
In this case, what are the roles of setOnClickListener and View.OnClickListener?
Within the constructor method of the Intent class, for the context, why can't we just put ".this" but we have to put in MainActivity class in the front? Under what kind of situation can we use ".this"?

setOnClickListener is a method. View.OnClickListener is an interface. The setOnClickListener method takes a View.OnClickListener as an argument. The syntax new Foo() { ... } defines an anonymous inner class instance that implements the interface Foo.
this refers to the instance, which in case of an inner class is the inner class View.OnClickListener instance. You can refer to the outer class instance (an activity which is-a Context) by scoping the reference with the outer class name.

You have to put MainActivity.this because the setOnClickListener is a interface in a View class and it contains a method onClick(View v); , if you will use this instead of MainActivity.this, it will refer to the Context of OnClickListener, when we specify MainActiviy.this it refers to the Context of MainActivity class. This concept is called Shadowing in java.

Related

I don't fully understand onClickListeners

So when we set an onClickListener to, say, a Button, it looks something like this.
private Button myButton = (Button) findViewById(R.id.my_button);
myButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
//do this
}
});
So we're creating a nameless anonymous class when we state new View.OnClickListener... and implementing the OnClickListener interface / and overriding it's onClick method. What I don't understand, is if we have no reference to this anon class, because it's nameless, how does the onClick() method get called? I've only ever implemented an anonymous class to override certain methods in said class, like this:
public class Foo{
public void bar(){
//do something
}
}
Foo foo = new Foo(){
#Override
public void bar(){
//do something else
}
}
This makes perfect sense to me because now, anytime I use the "foo" reference to call the bar() method, that reference will use the overridden version of bar. In the case of the Button, there's no reference to onClick(). I'm beyond confused about this.
If it helps your understanding, you could rewrite to this:
View.OnClickListener listener = new View.OnClickListener(){
#Override
public void onClick(View view){
//do this
}
};
myButton.setOnClickListener(listener);
The button holds the reference after listener goes out of scope, and can call the onClick callback on the held listener object.
What I don't understand, is if we have no reference to this anon class, because it's nameless, how does the onClick() method get called?
myButton is holding onto the instance of the anonymous inner class that you created. myButton, therefore, can call onClick() on it.
The onclick event is called in the button object and this object delegates to your anonymous class onclick with the reference you set.

How does setOnclickListner(this) work?

There are multiple ways to register callbacks when a Button is clicked. If I go by the following way:
public class MainActivity extends Activity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(this, "Hello onCLick", Toast.LENGTH_SHORT).show();
}
}
I don't understand how the method setOnClickListener(this) identifies that it should call onClick() method?
This refers to the activity. Because the Activity implements an OnClickListener calling button.setOnClickListener(this) gives the onClickListener that the Activity implements to setOnClickListener.
I recommend you look up info about implementing interfaces in Java if you want tot know more about this practise.
if you are aware about oops 'this' refer the reference of current object of class. a good explanation is define here
In above case MainActivity reference is refer as this here.
public void setOnClickListener(OnClickListener l)
is setter method define in class Button which hold the reference on "OnClickListener".
when you set setOnClickListener(this) it define you are passing OnClickListener reference as your activity so to make your activity as type on OnClickListener you have to implement the interface OnClickListener in your activity class as it is showing in your code.
public class MainActivity extends Activity implements OnClickListener
Its a callback listener which have method "onClick" you have to override that method
and when button is clicked that method is call by Button class so the event listener (which is you activity in current scenario) can listen to it.
I think I understand your confusion. When you read other SO answers or references like the View.OnClickListener, it feels like all the sentences are telling the same thing but nothing that really helps click.
What happens is, when a Button is clicked, it will notify all the objects that are listenning for it. You are subscribing your activity as a listener, to this event with the line
button.setOnClickListener(this);
So, on an event of a click, button knows that it should call the activity's onClick event.
I don't understand how the method setOnClickListener(this) identifies
that it should call onClick() method?
(Therefore, it s the button that calls the listener.onClick() method, in case there's a confusion there.)
Also, #nourikhalass has a point, you should first make sure that interfaces make sense to you.
Is it any clearer?
Your code has
MainActivity implements OnClickListener
but actually it is:
MainActivity implements View.OnClickListener
Maybe that is what confuses you.
"This" refers to current object.
To handle button clicks, an object must implement the "OnClickListener" interface and define what to do when clicks are received in "onClick" method. Then you can register that object as a listener for your button clicks.
In your case, your activity implements OnClickListener, and onClick shows a toast:
public class MainActivity extends Activity implements OnClickListener {
...
#Override
public void onClick(View v) {
Toast.makeText(this, "Hello onCLick", Toast.LENGTH_SHORT).show();
}
Therefore, your activity can handle button clicks, so you register it as a listener for your button:
button.setOnClickListener(this);
As "this" implements the required interface, is a valid listener.

using "this" to refer the "Context"

I can get the context with methods like getApplicationContext() or getContext() but I am a little confused with using "this" to get the "context" in the following example:
public class GeoActivity extends Activity {
private Button mTrueButton;
private Button mFalseButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geo);
mFalseButton = (Button) findViewById(R.id.false_button);
mFalseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// another method to get the context
// Context context = getApplicationContext();
Toast.makeText(GeoActivity.this, R.string.incorrect_toast, Toast.LENGTH_SHORT).show();
}
});
}
}
in this code we use GeoActivity.this to refer to the context, but I didn't understand what GeoActivity.this really is and what it is pointing to. also why in this case we cannot use simply this?
An Activity is a Context. If you use "this", it refers to the object in which the "this" appears, so if you use it inside a method of an Activity, it refers to the Activity. Because an Activity is a Context, you can use "this" when you need to pass a Context.
The situation is slightly complicated by the fact that you're using "this" inside the OnClickListener. You're creating an anonymous inner class to use as your OnClickListener. That's fine, but it means that if you just use "this" inside the OnClickListener, inside the Activity, then it'll refer to the OnClickListener rather than to the Activity. If you've got nested classes like this, you can specify which instance you want to refer to by putting the class name in front of the "this". So in your Toast.makeText method, "this" would refer to the OnClickListener that's inside your Activity, but "GeoActivity.this" refers to your Activity.
From Android documentation - Activity extends Context, so you can use Activity when Context is required
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity

Interface Vs anonymous class in android

I am little bit confused regarding backend working of anonymous class, like if we have a button and we are setting onclickListener
Button B = (Button)findViewById(R.id.myButton);
B.setOnClickListener(new onClickListener(){
public void onClick(View V){
Log.v("","Hello world");
}
));
What is here actually happening in backend ?Does this will implement interface of View.OnClickListener or something else???
Please look over this
How can an anonymous class use "extends" or "implements"?
http://docstore.mik.ua/orelly/java-ent/jnut/ch03_12.htm
Yes it is an instance of new unnamed class that implements the OnClickListener interface.
Anonymous classes must always extend a class or implement an interface.
b.setOnClickListener(new OnClickListener() {
public void onClick(View V) {
Log.v("", "Hello world");
}
});
In this case, you are creating a new anonymous (unnamed) class that implements the View.OnClickListener interface. This works because the setOnClickListener method takes an argument of type View.OnClickListener.

Calling an activity from a custom dialog

I guess this is just a simple question (I’m such a noob…)
I have this custom dialog box that has 3 buttons in it.
Now I want to call an activity from one of the buttons so
I tried this:
public class picturedialog extends Dialog implements OnClickListener {
Button Camera;
public picturedialog (Context context){
super (context);
setContentView(R.layout.picturedialog);
Camera = (Button) this.findViewById(R.id.pdButton1);
Camera.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
dismiss();
Intent myIntent = new Intent(view.getContext(), CameraActivity.class);
startActivity(myIntent);
}
});
...
}
Then the red squiggly line appears on startActivity(myIntent).
Upon hovering on it, eclipse tells me this: “The method startActivity(Intent) is undefined for the type new View.OnClickListener(){}”
Ehhh? Please orient me on how to do this properly.
Any help would be appreciated.
Suppose the name of your Activity is A, then you just do:
A.this.startActivity(myIntent);
The problem arises because "this" inside your inner class refers to the object of that inner class, when what you want is the object of the enclosing Activity. A.this will refer to that.
If you aren't enclosing this class in an Activity, then try calling the startActivity from method using the context that you passed into the method, e.g. context.startActivty(myIntent).
The startActivity method belongs to the Context class.
I am sure you are overcomplicating with subclassing from Dialog. Try to follow to the dialog tutorial - https://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
Note that dialogs are created on the fly (in Activity.onCreateDialog()) without the need to have your own custom dialog classes. Since you set a listener being inside of the wrapping activity (if you follow the tutorial), then you are able to call startActivity(myIntent), because all the fields/methods of a wrapping class instance are available for an instance of an inner class.

Categories

Resources