Context In Android

If you can’t explain it simply, you don’t understand it well enough — Albert Einstein

Context in Android is one of the most used and abused objects.

So what exactly is context? This is the agenda of this article.

Dictionary meaning of Context is “the situation in which something happens”

So we can say ApplicationContext provides the information or handle of the environment in which our Application is running, ActivityContext provides the information or handle of the environment in which our Activity is running and so on…

Let’s breakdown it further

Background of Context:

Unlike typical OSs, Android applications and processes are independent. Because it is independent, the application can remain running even if the process terminates. For example, this is why services and broadcast receivers can work in the background regardless of whether the application is running or not.

Because of these characteristics of Android, processes and applications are managed separately. Processes are managed by the operating system, and applications are managed by an object called ActivityManagerSerivce.

But, the application and ActivityManagerService do not communicate directly, they communicate indirectly through Context.

Context in Android provides an interface to access application specific classes and resources (for example, to access any resource under the /res directory) as well as provides methods to perform application-level operations such as launching activities, broadcasting and receiving intents, and accessing shared preferences and databases etc.

In short, Context represents a handle to get environment data. It’s actually a bridge between our app and the Android System.

Context is an abstract class itself, so who implements it then?

Android Context Class Hierarchy

Its implementation provided by Android Framework’s itself.

Behind the scenes,Context’s implementation (ContextImpl in the diagram) is being provided by AMS (Activity Manager Service) which is a system process to manage running status of Activity and other components.

Even ContextWrapper inherits from Context but does not implement it. Instead, it gets implementation from ContextImpl and wraps all of its functions. So, ContextWrapper simply uses the methods implemented by ContextImpl.

ContextWrapper is a convenient way to modify the behavior of a Context object, such as adding additional functionality or overriding existing behavior, without changing the original Context itself.

ContextThemeWrapper allows you to change the visual appearance of an activity or view by applying a different theme to it.

At the third level of hierarchy we can see Application and Service which directly inherits from ContextWrapper this is because they don’t need a Theme and should not contain a theme since their purposes are not building a UI.

But Activity, really needs a theme because its an Android Fundamental Component whose purpose is building and managing UIs for our apps. So it inherits from ContextThemeWrapper which contains information about theme files of our app that are declared in our AndroidManifest.xml file.

How many Context in an Application?

From above discussion, we can conclude that
Number of Context = 1 Context per Activity + 1 Context per Service + 1 context for whole Application

So, in an Android project, we have one Context for the Application class, one Context for each Service component and one Context for each Activity component.

For other components like Content Provider, Broadcast Receiver which are not subclass of Context, so they are not counted, but we need to pass context object to them when create a new one.

So, based on the above discussion we can conclude few important points about the context:

  • Context is basically the current state of the application.
  • It can be used to get information regarding the activity and application.
  • It can be used to get access to App specific resources (for example, to access any resource under the /res directory), databases, file systems and shared preferences, etc.
  • Context provides methods to perform application-level operations such as launching activities, broadcasting and receiving intents etc.
  • We get the Context through the Android Framework or Android System, our Application and Android System communicate through Context only. It acts as a bridge between our Application and the Android System.
  • A regular class with Context can be called a Component (for example: Activity, Service, ContentProvider, BroadcastReceiver).

Now let’s see with which context what we are able to do:

  1. Application Context:

It is our global context which means its instance is created only once (singleton instance) and is used across whole application.
This context is tied to the lifecycle of an application. The application context can be used where you need a context whose lifecycle is separate from the current context or when you are passing a context beyond the scope of activity.

Example Use: If you have to create a singleton object for your application and that object needs a context, always pass the application context.

If you pass the activity context here, it will lead to the memory leak as it will keep the reference to the activity and activity will not be garbage collected.

In case, when you have to initialize a library in an activity, always pass the application context, not the activity context.

You only use getApplicationContext() when you know you need a Context for something that may live longer than any other likely Context you have at your disposal.

2. Activity Context:

This context is available in an activity. This context is tied to the lifecycle of an activity. The activity context should be used when you are passing the context in the scope of an activity or you need the context whose lifecycle is attached to the current context.

Example Use: If you have to create an object whose lifecycle is attached to an activity, you can use the activity context.

3. Service Context:

It’s a context for Service class in Android and used for downloading operations or listening a music which sometimes has a very very long lifetime than our application. I mean it lives as long as our service lives.

For example, Service Context is passed into the MediaPlayer.create(). When the service is destroyed, the MediaPlayer is destroyed too, so passing in the Service Context here makes a lot of sense.

class PlayAudioService : Service() {
private val mediaPlayer: MediaPlayer by lazy {
MediaPlayer.create(this, R.raw.daybreak)
}
}

4. Base Context:

It exists for ContextWrapper actually. When AMS creates an implementation of the context abstract class, ContextWrapper gets that implementation with its getBaseContext() function, so there is no actual use-case of BaseContext in app development.

5. Broadcast Receiver

Unlike activities and services, broadcast receivers do not inherit Context.

In order for the broadcast receiver to use the Context, the Context is retrieved through the onReceive() method.

public abstract void onReceive (Context context, 
Intent intent)

6. Content Provider

Content providers can get Context through getContext(). This context is the application context and can be used as the application context. You can get it using the getContext() method.

What Context can do?

Context is powerful, but it still has some restrictions. Since context is implemented by ContextImpl, so in most situations we can use activity, service and application context in common. However, in some situation like start a Activity or pop up a dialog, it must use Activity context since a new Activity is based on another Activity to form a stack, also a popup dialog need to show on top of Activity except some system alert dialog.

Usage of different Contexts in Android

Now, there are two noteworthy limitations with Application and Service contexts.

You should not inflate a layout from them.

Remember, It is able to inflate the layout, but Application and Service contexts do not inherit from the ContextThemeWrapper class, and thus, do not have access to the application’s theme (custom theme), so the inflated layout would have the default theme (default theme of the android system).

Usually, you should not start an Activity from them.

When an Activity is started from another Activity, they are properly added to the Activity stack.
But if we use Application or Service context to start an Activity with standard launch mode, it will throw exception “android.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
Is this really what you want?” This exception is because the non Activity context do not have the back stack. So from service and application is only to use FLAG_ACTIVITY_NEW_TASK (this activity will become the start of a new task on this history stack.) to start an Activity, which is not recommended.

When not to use getApplicationContext() ?

  • It’s not a complete Context, supporting everything that Activity does. Various things you will try to do with this Context will fail, mostly related to the GUI.
  • It can create memory leaks if the Context from getApplicationContext() holds onto something created by your calls on it that you don’t clean up. With an Activity, if it holds onto something, once the Activity gets garbage collected, everything else flushes out too. The Application object remains for the lifetime of your process.

The Rule of Thumb

In most cases, use the Context directly available to you from the enclosing component you’re working within. You can safely hold a reference to it as long as that reference does not extend beyond the lifecycle of that component. As soon as you need to save a reference to a Context from an object that lives beyond your Activity or Service, even temporarily, switch that reference you save over to the application context.

Internal Code Flow Involved In Context Creation:

That’s it for now.

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top