Context is everywhere in Android: you need it to inflate layouts, start activities, access resources, and get system services. But “just pass a context” hides a lot of nuance — and the wrong choice is a classic source of memory leaks.

The Context hierarchy

Context is an abstract class. The concrete implementation that does the real work is ContextImpl. You rarely touch it directly. Instead you interact with:

Context (abstract)
└── ContextWrapper
    ├── Application
    ├── Service
    └── ContextThemeWrapper
        └── Activity
  • ContextImpl — the real implementation, created by the framework.
  • ContextWrapper — wraps another Context and delegates calls to it.
  • Application, Service, Activity — all ContextWrapper subclasses.

What ContextWrapper does

ContextWrapper holds a reference to a base context and forwards every call to it. This is the decorator pattern: it lets the framework attach extra behavior without reimplementing all of Context.

// Simplified from the framework
open class ContextWrapper(base: Context) : Context() {
    private var mBase: Context = base

    override fun getSystemService(name: String): Any? =
        mBase.getSystemService(name)

    override fun getResources(): Resources =
        mBase.getResources()
    // ...delegates dozens more methods
}

Activity extends ContextThemeWrapper, which extends ContextWrapper and adds a theme. That’s why an Activity context can inflate themed views correctly while the Application context cannot apply your activity theme.

Application vs Activity context

The two you’ll choose between most often:

Use caseRecommended Context
Inflating views / applying a themeActivity
Showing a DialogActivity
Starting an ActivityActivity
Long-lived singletons / librariesApplication
WorkManager, Room, DI graphApplication

The memory leak trap

Holding an Activity context past the activity’s lifetime leaks the entire activity — and its view tree.

// BAD: a singleton holding an Activity context leaks it forever.
object AnalyticsCache {
    var context: Context? = null
}

// In an Activity:
AnalyticsCache.context = this // leaks this Activity!
// GOOD: store the application context for long-lived references.
AnalyticsCache.context = applicationContext

A simple rule

If the object outlives the activity, use applicationContext. If it needs a theme or shows UI, use the Activity context.

Get that distinction right and most “why is my activity not being garbage collected?” questions answer themselves.

Key takeaways

  • Context is abstract; ContextImpl is the real worker.
  • ContextWrapper decorates a base context and is the parent of Application, Service, and (via ContextThemeWrapper) Activity.
  • Only Activity carries your theme — use it for UI.
  • Never let a long-lived object hold an Activity context.