Working with Android Context in non-Activity Class - java

I often have the Problem, that I cannot use something because of the Context it needs.
For example, if you have a Toast you want to use in a Class for something, you need Context but you cannot use any context, because you are not in an Activity.
Now what I did was, I gave that Class I made a variable "context" which is set in the constructor, but I don't really think this is right.
So how do I handle the context in a non-Activity Class?
Thanks in advance :)

Never keep a reference to context as a member variable or as a static variable, as it might lead to memory leaks as it becomes difficult for the GC to collect the references.
Since you are using context in a non activity class, I assume that class to be some kind of a helper class with static method blocks.
For eg :
public class ToastMessageHelper {
public static void showToast(Context context) {
Toast.makeText(context, "Hello",Toast.LENGTH_SHORT).show();
}
}
It is better to pass context as a parameter to the methods which require the context to execute.
Now, you can simply call,
ToastMessageHelper.showToast(context);
in your activity or a fragment. Hope this helps!

If you aren't in an activity, you can always use getApplicationContext() which will return the context for the app.

Yes you are right, you usually pass the Context to the required object or class which may require it, sometimes you pass it in the constructor, but knowing that the context may change sometimes is better to pass it right in the method. It is up to the developer choose the right scenario.
It is true that in some situations you could need another way to get or pass the context, but usually passing it in the constructor or methods is enough

A sophisticated way to use context in a non-Activity class is the ContextWrapper.
You can read a little bit about this here:
Best practice to pass Context to non-activity classes?
or here
http://itekblog.com/android-context-in-non-activity-class/
You could also use a variable "context" or pass by parameter in a static method and you should be fine, being in mind you can have some issues with this practice.

Related

Android - Why people refer to a static context inline repeatedly, instead of pass it in the Method() once?

I'm approaching completion of my first true App..
Along my road (in the past couple years) I've seen many examples of code.
One thing is consistent: I always see the use of static context references such as:
getApplicationContext(), this.getActivity(), and many other such references..
But earlier today, after asking how to retrieve Context from a Method within a Receiver,I was told simply "pass it the Context", ex: public void receiverMethodCall(Context context).
My Question is: If it's that simple, why do people frequently make repeated static context references inline within their code, over and over again, instead of simply passing the containing Method a Context to begin with, and referring to it using "context" when needed?
I Hope that I got your question meaning - you got your answer and told to pass on the context as a context typed variable - but do not forget that when you want to call your method and pass it a context, you will have to know what this context is and initialize it.For example, if you want to make a Toast one of the method parameters is context and if you are using a lot of Toasts it would be better to have context reference and use it for every time you want to show a Toast(or use any other method that requires context.)rather than using this.getActivity() orgetApplicationContext().By doing this you can prevent a duplicated code and you won't need to refer to the context in your code a lot of times, now for the question about "why do people frequently make repeated static context references inline within their code".
I can think of one case when it won't be a bad thing to make 2 context reference: let's say that you have 2 methods in the same activity that are using context - if those methods are used once then you can create context reference inside the method and let the garbage collector handle that reference.I do have to say that I agree with you, I think that if its optional just pass context to your method and let it use it, its really simple solution.

Preventing memory leaks in Android

Is it wise to get a reference to a Context object in every Activity where I need a Context by getting the Application context? I have learned that it can create memory leaks to throw around your Activity's context object but when you create complex Activities it seems that a Context object is almost always necessary. I was previously declaring a Context variable at the top of the Activity class and initializing it with the "this" keyword in onCreate. I already know this can be poor form, but is it ok to initialize the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
There is really no need of a Context field in your Activity, as you can always get the context using getBaseContext(), getApplicationContext(), or this (since Activity itself is Context).
You might have to pass your Context to other classes if you want to keep you Activity class thin. This is perfectly ok as long as the lifecycle of those classes is the same as the lifecycle of your Activity. This means, when your Activity is destroyed, no objects should have the reference to the context you passed.
Static methods are extremely good as long as they don't refer to static fields. Use static methods if they don't have a state. Static fields are dangerous for a lot of reasons. So use them only for the right scenarios.
I think you need to understand the differences between Application Context and Activity Context, please refer to the answer here.
But is it ok to initialise the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Why do you need to initialise a context object? Activity itself is already a context. For example:
Intent intent = new Intent(this, MainActivity.class);
You don't need to initialise a context from application context as the activity context has more capabilities. Please refer to this link.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
For sending a data from one activity to another activity, you might need parcelable object and bundle, or Event Bus to decouple both sender/receiver activity.
For static method, you might need to group them under a Utility class.

Can I and should I pass a Context to a static method outside of the UI?

I've looked around but never found a straightforward answer to this question. I'm wondering what would happen if I use a pattern that requires me to pass a Context to static methods to do things on the backend. For instance:
public static Observable<CreateThing> createNewThing(String thingName, Context context) { // Passing Context in
return RestNetworker.handleResponse(ServiceGenerator.createService(Service.class).createThing(thingName))
.doOnNext(response -> DatabaseHelper.getInstance(context).createThing(new Thing(response.getThingId(), thingName))); // context used to get instance of DatabaseHelper
}
This method makes an API call and then writes the object to the database locally after a success response. However, I need to pass a Context to create the instance of the database helper. I could alternatively pass the database helper itself, but then I'd be creating the instance (rather getting it, since it's singleton) in the Activity code and I'd rather not do that either.
My question really is: If, say, a user exits the Activity while the API call is in progress, will this Context instance get GC'd and result in an NPE when the response comes back? I've done this kind of thing before and never noticed that issue, but it really seems that there should be some consequence of doing this. I know that other developers must do some things off the UI thread that require a Context, so this should be a relatively easy question to answer.
Thanks guys! Please let me know if you need any more information to provide better context. Heh.
The rule is that you do not pass an instance of the Activity to some object that may keep a reference to it outside of the lifecycle of the Activity. This will cause a memory leak, as the GC will not be able to free the memory allocated to the Activity and the entire view tree contained within. In those instances you pass getApplicationContext().
In cases where the context will only be referenced for the duration of the method call, passing the Activity as this is fine.
In your case, it seems like DatabaseHelper may store a reference to the context, so I would use getApplicationContext() Note that you would not get NPE because the reference was GC if you passed an Activity, that doesn't make sense - if the DatabaseHelper was storing a strong reference, this could not occur (at least on the reference to the Activity itself).

Getting context of Android inside additional classes

Created java class DBOperations i android project to realize database operations but found that some operations need Context object. Couldn't get it with this or getapplicationcontext method. I decided to pass context object as a paramether,e.g.
Mymdhod(this);
Is it correct way or there are other methods to get application context?
If all things you need the context for can be done in the constructor, consider passing the context as a parameter to the constructor and immediately initialize everything you need the context for.
Otherwise, if you need the context in a public method, pass the context as a parameter to this method.
What you shouldn't be doing is keeping a reference to the context as a member variable. The reference you are holding might be invalidated upon traversal through the activity lifecycle and holding the reference might cause memory leaks as further described in this article.
Yeah, if you need the context in your own classes, the best way is to pass it in like you are doing.
Using parameters of the method calls , you can pass the context of activity and use them in another classes.
For instance:
Obj.methodName(context)
And method
public methodName(Context context){
// do something with context
}

Declaring variables as static within MainActivity and accessing them from other classes

Many times when I have been developing android apps, in order to access some important variables such as getApplicationContext() or other variables such as Buttons or Edittexts, which are normally not accessible outside MainActivity but required in some other class in the same project, I have been using this technique, that is
Within MainActivity (for getApplicationContext() case):
private static Context context = null;
and inside the onCreate method, I do :
context = getApplicationContext();
and I then access the context ( to display a toast message , for example) by using:
Toast.makeText(MainActivity.context,"Message",Toast.LENGTH_LONG).show();
in my other class. Similarly to get or set the text in an EditText variable and so on.
My questions are:
1)Is this the best method for my problem definition?
2)If no, is there a better way?
3)if no, what are the disadvantages of this technique?
3)Can the same technique be extended to functions in the Mainctivity?
EDIT: I do not require another Activity here, rather I am just splitting the task of the app into separate classes (or objects).
My questions are:
1)Is this the best method for my problem definition?
no this is not the best way of solving this.
2)If no, is there a better way?
yes to save static information you should be using something like a headless fragment so that the android framework can handle the garbage collection on unused classes and data
3)if no, what are the disadvantages of this technique?
disadvantages are many :) firstly memory leaking cause that static var cant be garbage collected at all so it stays in memory.
secondly you should not use edit texts from the main activity somewhere else cause there is no garantee that the mainactivity will still be there cause if you move away from it android might kill it to save memory.
all screens should be selfcontained and data must be transfered with intents and Bundles()
3)Can the same technique be extended to functions in the Mainctivity?
create seperate helper classes that sit within a static class like helpers. MainActivity is not a static class and shouldn't be a static class

Categories

Resources