The context also gives you access to the System Services. This enables you to interact with the various managers, some examples being the:
- AlarmManager – you may want to have a look at our tutorial, Scheduling Android’s Repeating Alarms for more on using it
- AudioManager
- LocationManager
Context subclasses
You’re probably familiar with two of the Context class’s subclasses:
- The Activity class – for more on Activities, check out our tutorial, Android Activities
- The Service class – here’s a tutorial on Services that may interest you, All about Services
Both the Activity and Service classes are subclasses of the Context class. So you can use instances of them wherever you need a context.
The Context class also gives you access to a number of useful methods. Here are some of the more popular ones:
- getAssets() - returns an AssetManager instance for your application's package. You’ll need the Asset Manager to access your raw asset files
- getPackageName() - returns the name of the application's package
- databaseList() – returns an array of strings naming the databases associated with this Context’s application package
- fileList() – returns an array of strings naming the private files associated with this Context’s application package
- getCacheDir() – returns the absolute path to the app’s cache directory on the filesystem. Have a look at the tutorial, Using Android’s file system for saving application data to see how it’s used
- getContentResolver() – returns a Content Resolver instance for your app. You may be interested in having a look at Creating our Custom Content Provider series of tutorials where we show you how to use Content Resolvers to get data out of a database
- getFilesDir() – returns the absolute path to the directory on the filesystem where files created with openFileOutput() are stored. Have a look at the tutorial, Using Android’s file system for saving application data to see how it’s used
- getResources() – returns a resource instance for the app’s package. You’ll use it to access your resources. If you’re interested, check out the tutorial, Accessing application resources to see how we use it
- getSharedPreferences() – returns the contents of a preference file. For more on Shared Preferences, have a look at our tutorial, Using Android’s SharedPreferences to save persistent data
The View class
A good example showing the role of a context can be seen when we use the View class.
The View class relies on the context to get information about the app’s environment which is necessary to be able to construct the View object. Consequently all of its constructors accept a context parameter.
The View needs to know which theme, strings, dimensions, etc. to use. It’s the context that enables it to access this information.
Passing the context to the view when it is being constructed, gives you the flexibility to use a different context to construct the view, as the one used by the activity, for example. This gives the view access to resources other than those used by the activity. We’ll show you an example later.
If you need to know which context the view is running in, call getContext(), from the view.
So where would you use a context?
- you would use it when creating views, adapters and Toast messages for example
- you would use it when accessing System Services too, for example:
- to get a LayoutInflater to inflate a layout resource
- to get an InputMethodManager to interact with a keyboard. You may be interested in checking out our tutorial, Android’s soft keyboard. An introduction for more on using keyboards
- you would use it when accessing components, like a Content Resolver which you’ll use to retrieve data from a database
Essentially there are two types of Context
- Application context – which is tied to the lifecycle of the application
- Activity context - context is tied to the lifecycle of an Activity
This means that they have access to different information about the application environment.
So which context should you use?
The Application context
You can call getApplicationContext() to get the application’s context in the current process.
You can also use getApplication() which will return the application that owns the activity. Since the Application class extends the Context class, it can be used as the application context.
The application context will remain the same throughout the app’s life cycle.
You could for example use the application context:
- to display a Toast message
- to access settings and resources shared across multiple activity instances
- if you need a context with global scope
Note that some “experts” warn against using it unless you know why you should use it and then only to use it when you absolutely have to.
Others maintain that you should use it as the default context for everything, except for the odd occasion, like when displaying a progress dialog.
Unfortunately the documentation can be confusing in this regard so in the end you’ll have to decide for yourself.
The Activity context
The activity context is attached to the Activity’s life cycle and is destroyed along with the activity.
Since the Activity class extends the Context class, an activity is a Context. You can therefore use the activity’s class name or this for an activity context.
You can also use getBaseContext() to return an activity context.
Note that some “experts” warn against using getBaseContext() and suggest that you rather use the context that you have.
Using context in a fragment
You can use the getActivity() method to get the activity associated with the fragment. As the Activity class is a subclass of the Context class, the returned activity is therefore a context.
Check out our tutorial on fragments, Dynamic layouts using fragments if you’re interested in learning about fragments
Consider the following when making your choice as to which context to use:
- generally use the context available to you in the component that you’re working in. So, for example if you’re working in an activity, use the activity’s context
- use the application context if you’re saving a reference to a context from an object that lives beyond your activity or service
A word of caution: Don’t pass an object around that is tied to an activity. It will leak the views and resources associated with the activity. (The activity maintains a hold on them so they can’t be garbage collected which means that valuable memory is wasted).
Memory leaks
Memory leaks happen when you keep a reference to a context which prevents the Garbage Collector from collecting it (and releasing valuable memory).
Most memory leaks are caused by keeping a long-lived reference to a context.
The context is mainly used to load and access the app’s resources. This is why all views require a context as a parameter in their constructors.
Usually it’s the activity context that is used to construct the views. The result is that the views have a reference to the entire activity, including its View hierarchy and all its resources. So if you leak the context, you leak a lot of memory.
Read more in the original blog post covering memory leaks.
Here’s a summary of the suggested methods to avoid context related memory leaks:
- don’t keep long-lived references to the activity’s context. Any references to the activity should be destroyed along with the activity
- try using the application context instead of the activity context
- avoid non-static inner classes in an activity if you don’t have control over their life-cycle. Rather use a static inner class with a weak reference to the outer class
Here’s how you could provide a current context in an anonymous inner class
- Use Context.this instead of this
- Use getApplicationContext() instead of this
- Explicitly use the class name (i.e. the activity, the outer class)
- Call a function that is declared at the right context level
Using the class name
Use TheActivityClassName.this in the inner class to access the outer TheActivityClassName class’s context.
Here’s an example:
The above code is used within the AppMenuActivity activity’s onCreate() method so we use the activity as the context in the onClick() method
A quick explanation
Calling new View.OnClickListener() creates an anonymous inner class. We need to pass the outer class’s context to the intent that we’re creating in the inner class. As Activities are a subclass of the Context class, they are therefore a Context. We can then use the activity as the context within the onClick() method.
Using different contexts
We have two themes. One is used for the application and the other for the activity
A quick explanation
We create two TextView objects in an activity’s onCreate() method:
- textViewApp - uses the application context as we pass the context returned by the getApplicationContext() method as a parameter to the view’s constructor
- textViewActivity - uses the activity’s context, this as the parameter in the view’s constructor
We then add the views to our layout. Here’s a screenshot of what it looks like when the app runs:
The red text is displayed because the text view is constructed using the activity’s context. The grey text is displayed in the TextView that was constructed using the application’s context
A quick explanation
Each of the text views accesses the resources available to them from the context supplied to their constructors. These different contexts supply different information about the application’s environment.
We specify in the manifest that the app should use the AppTheme while the activity should use the ActivityTheme.
The two text views are constructed using different contexts so they use different themes:
- the application context uses the AppTheme
- the activity context uses the ActivityTheme
I hope that you have found this tutorial helpful.