I'll try really hard to turn this into one comprehensive question:
I'm writing a method to get a String that contains the name of an Android device's city, as determined by the LocationManager
and getLastKnownLocation()
and all that.
Then I realized I'd need to do the same thing again in another activity, so why not just make an entirely separate class (LocationFinder
) that I could use across my program, instead of writing duplicate code everywhere?
But I've run into problems that confuses me. For instance, if I make this class (LocationFinder
), should it extend Activity, even though it is never actually visualized? All this class would do is have a variety of getters like getLastKnownCity()
or getCurrentCity()
and return strings. I assumed it wouldn't HAVE to extend the Activity class, since it's really not an activity.
But then what Context do I use for:
Geocoder geocoder = new Geocoder(Context context, Locale locale)
?
This made me assume it MUST be an activity. So I extended Activity, and replaced the constructor with
@Override
protected void onCreate(..............
but for some reason, that never ends up getting called, even when I put
String city = new LocationFinder().getLastKnownCity();
My very first line of LocationFinder
's onCreate()
is
System.out.println("HEY!")
and it never even gets to that. I get a null pointer at android.internal.os.LoggingPrintStream.println()
and other stuff.
Plus, there's a bunch of system constants that come from Activity classes. For instance, I need to get at LOCATION_SERVICE
, which is a String, which I can't get without extending Activity. Sure, I could cheat and just put in the literal string, but that feels wrong.
No. From the Android docs
Think of an Activity as a screen the user sees.
The
Activity
class extendsContext
, as do a lot of other classes includingApplication
. A context provides access to resources associated with the class which extends the context.You only need, and should only use, an Activity context when required to interact with resources associated with that Activity and methods implemented by the concrete Activity class. When you do need that access to that context, then you would pass it to the class needing access, typically as an argument to a constructor of that class.
If you ever do pass an Activity context outside of the activity extending it, make sure that the scope and lifecycle of the reference is less than or equal to the extending activity otherwise you will leak large amounts of memory if the activity is destroyed since the garbage collector cannot free the memory since there is a reference to the context.
If you take a look at the constructor for Geocoder you will see that it takes a Context as an argument, as you know. There is a clue as to why the Context is needed in the description:
The reason the Context is required is to gain access to system information about the platform locales and the current system locale.
So in your example, you could simply pass the Application context to the constructor, which you can get a reference to with
getApplicationContext()
You can get it from the application context.
When constructing your class, you can have a constructor that takes in a Context and assigns it a local Context object within your class.
And then when you try to access this class, make sure you initialise it like:
Of course, you can't access a context from every class that you will be running. So a reference to a View can suffice.
EDIT: If possible, use frogmanx's answer. This should only be used when his answer is not possible to use. (ie. singletons that need a context right off the bat.)
Sounds like you should extend Application and not Activity.
Make your Application something like this:
Then add this attribute to the application tag of the manifest:
After all that, you can get a Context by calling
MyApplication.getInstance()
from anywhere.