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
Related
I have only one activity in my app. Before I just stored my views and dialogs static in the activity, so I could access them from anywhere. But I know that this is bad practice because it leads to memory leaks.
So I made them non-static, but now I need to have a reference to my activity deep down in my view hierarchy, to access the views and dialogs stored in the activity.
Example:
My MainActivity has a dialog called a and a custom view called b. How can the onClick method of b show the dialog a?
or in code:
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
#Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
}
}
public class CustomView extends Button implements OnClickListener {
public CustomView(Context context) {
super(context);
setOnClickListener(this);
}
#Override
public void onClick(View view) {
//wants to show dialog a
MainActivity.a.show(); //Not possible -> a is not static
mainActivity.a.show(); //<-- needs a reference of the activity
// but where from?
}
}
MainActivity mainActivity = (MainActivity) getContext(); won't work because getContext() is not always an activity context.
UPDATE:
I posted an answer below!
For some reasons StackOverflow only lets me accept my own answer in two days
I do not know what exactly your view hierarchy looks like.
I picture your problem for example as:
Activity A has a recyclerview R, now every viewholder H in R should be able to trigger some method in A.
In such a scenario it would be feasable to pass a reference of your activity to your recyclerview adapter and then the adapter passes it to the ViewHolder.
Which then uses it in the onClick method of your (viewholder's) view.
Here, you could use the "callback" pattern. There are many posts about this on stackoverflow, e.g. here.
So the implementation steps would be:
define interface
let your activity implement that interface
let your adapter take the interface as a constructor parameter and pass your activity. (in this example: you have to repeat the step with your viewHolder, pass the interface from the adapter)
use this interfaces method in the onClick method -> this will then trigger your activities method
The implementation depends on the actual hierarchy. If your other view is in a fragment, then you could also use a (shared) ViewModel.
According to your picture I was thinking of the callback-pattern approach first.
You could override onClick in MainActivity; there is probably no need to do it in the class definition itself.
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
#Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
a.show();
}
});
}
}
This is a very common pattern in android and I don't know what your view hierarchy looks like but it should work in most cases.
I am having trouble understanding why any class extending Button would need to implement View.OnClickListener. It makes much more sense to create listeners in activities or have MainActivity implement OnClickListener.
A few minutes a go there was an answer here that turned out to be correct.
I don't know why the author deleted it, but it had a link to this answer:
private static Activity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (Activity) context;
}
So everytime you need the activity you just can call Activity activity = unwrap(getContext());.
I don't know if it is really intended to do it that way or if it is a workaround, but it does its job (atleast in my case).
When i am applying this Geocoder in my Activity and using context as this ,then i m redirected to another activity I'm my android application.So i want to know that writing this keyword in context signifies what?
The keyword this represents the instance of the current class.
You can access the properties and functions of the current class with this keyword.
For Simple Example,
Suppose, you activity name is MainActivity and you want to print Toast in Main Activity then just write:-
Toast.makeText(this, "Hello...", Toast.LENGTH_SHORT).show();
Here, just need to write this and automatically it takes instance of current Activity or class and display Toast message in Main activity.
this as Context
The Activity class extends the Context class in android. Therefore this keyword can be used in the Activity class to reference both an Activity object and a Context object as an object.
And also other Multiple Usage this keyword
It can be used to refer current class instance.
It used to invoke current class method (implicitly)
It can be passed as an argument in the method call.
It can be passed as argument in the constructor call.
It also used to return the current class instance from the method.
You can also refer this keyword in android for more understanding:-
this always signifies the current class object.. when you are passing this in activity its passing the object of activity which it self is a Context
Lets say you have an activity and you add a click listner on button (i am juts writing a sudo)
public class MyActvity extends AppcompatActivity{
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
context=this;//here this will signigy the activity
navigationView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
this //here this will be the object of clickListener
MyActvity.this//Now this is signifying the context
}
});
}
}
I hope it helped
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.
I am pretty new to android app development and java and I encountered the following error when trying to call a method from another class:
Cannot make a static reference to the non-static method showToast(String) from the type LoginActivity
The reason I want to call this in the other class and not instantiate it in the class itself is because of adaptability and upgradeability issues. This seems a fine concept by me or is it something that is way overrated?
The relevant code is:
CreateAccountActivity
public class NewAccountActivity extends Activity{
private Button mCreateAccountButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newaccount);
mCreateAccountButton = (Button) findViewById(R.id.createaccount_button);
registerButtonListeners();
}
private void registerButtonListeners() {
mCreateAccountButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LoginActivity.showToast(getString(R.string.createaccount_message));
}
});
}
}
LoginActivity
public void showToast(String toastString) {
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root));
ImageView image = (ImageView) layout.findViewById(R.id.toastImage);
image.setImageResource(R.drawable.android);
TextView text = (TextView) layout.findViewById(R.id.toastText);
text.setText(toastString);
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
}
Creating a new LoginActivity object and then calling showToast on it makes the error messages go away but gives me a NullPointerException instead.
if you want to call showToast in the static way you have to make the method showToast static.
public static void showToast(...)
Edit: where do you get the NullPointerException?
The problem is that you should not create Objects from Activity on you own. Activities should be instantiated through the system, they go through a fairly complex lifecycle that is managed by the OS itself and won't work if they are not following the lifecycle correct.
There are two possibilities to create maintainable code that actually runs for your problem:
Create a static helper function somewhere in another class and pass in an activity object that you use to get a layout inflater and actually show the Toast. This way every activity can use the showToast method without dependencies between your activities.
Create a base activity that is extended by all your activities that has a public method showToast. This way you do not need to pass in a context method and every one of your activities just has the ability to show a Toast. This has some problems if you are extending different Activities like FragmentActivity, ListActivity, TabActivity.
I would go with the first method and create something like a Util or ToastUtil class that holds the Toast functionality at one place for all your activities.
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.