Skip to content
beginner Phase 2 · Android Fundamentals

Context

Understand what Context is, when to use Activity vs Application context, and memory leak risks.

35m
0 problems
Topic Progress 0%

What is Context?

What is Context?

Context is an interface that provides access to application-specific resources and classes, as well as calls for application-level operations. Think of it as a handle to the environment your code runs in.

Every Android component is a Context:

  • Activity is a Context (and a Window)
  • Service is a Context (but no UI)
  • Application is a Context (app-wide)
  • ContentProvider is NOT a Context directly (use context property)

What Context Provides

// Accessing resources
val appName = context.getString(R.string.app_name)
val color = ContextCompat.getColor(context, R.color.primary)
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_launcher)

// System services
val inflater = context.getSystemService(LayoutInflater::class.java)
val connectivity = context.getSystemService(ConnectivityManager::class.java)
val alarmManager = context.getSystemService(AlarmManager::class.java)

// Starting activities
context.startActivity(Intent(context, DetailActivity::class.java))

// File and database access
val file = File(context.filesDir, "data.json")
val db = Room.databaseBuilder(context, AppDatabase::class.java, "app.db").build()

// Package information
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
val appName = context.applicationInfo.loadLabel(context.packageManager)

Activity Context vs Application Context

Activity Context is tied to the activity lifecycle. It knows about the window, theme, and UI state. Use it for operations that need to interact with UI.

Application Context lives as long as the app process. It has no window or theme awareness. Use it for operations that don't need UI.

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Activity context — has window, theme
        val dialog = AlertDialog.Builder(this) // this = Activity Context
            .setTitle("Alert")
            .setMessage("Hello")
            .create()

        // Application context — no window, no theme
        val appContext = applicationContext
        // appContext cannot show dialogs (no window)
    }
}

When to Use Application Context

Application context is safer for long-lived operations because it doesn't depend on activity lifecycle:

// Correct — Application context for singletons
object DatabaseProvider {
    private var instance: AppDatabase? = null

    fun getDatabase(context: Context): AppDatabase {
        return instance ?: synchronized(this) {
            // Use applicationContext to avoid leaking Activity
            val builder = Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "app.db"
            )
            instance = builder.build()
            instance!!
        }
    }
}

// WRONG — Using Activity context in a singleton
object BadDatabaseProvider {
    private var instance: AppDatabase? = null

    fun getDatabase(context: Context): AppDatabase {
        return instance ?: synchronized(this) {
            // This leaks the Activity!
            val builder = Room.databaseBuilder(
                context,  // Activity context!
                AppDatabase::class.java,
                "app.db"
            )
            instance = builder.build()
            instance!!
        }
    }
}

Context and Memory Leaks

Context and Memory Leaks

The most common Android memory leak is holding a reference to an Activity context after the activity is destroyed. This prevents garbage collection of the entire activity and all its views.

Common Leak Patterns

1. Static reference to Activity context:

// WRONG
object LeakyManager {
    var context: Context? = null

    fun init(context: Context) {
        this.context = context  // If activity context, it leaks
    }
}

// CORRECT
object SafeManager {
    var context: Context? = null

    fun init(context: Context) {
        this.context = context.applicationContext  // Safe
    }
}

2. Inner class holding implicit reference to Activity:

// WRONG — Kotlin lambdas in coroutines
lifecycleScope.launch {
    delay(10000)
    // Activity might be destroyed after 10 seconds
    Toast.makeText(this@MainActivity, "Done", Toast.LENGTH_SHORT).show()
}

// CORRECT — Use viewLifecycleOwner scope
viewLifecycleOwner.lifecycleScope.launch {
    delay(10000)
    // If view is destroyed, coroutine is cancelled
    Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show()
}

3. Handler with delayed messages:

// WRONG
val handler = object : Handler(Looper.getMainLooper()) {
    override fun handleMessage(msg: Message) {
        // Activity context leaked if message is pending when activity is destroyed
    }
}
handler.sendMessageDelayed(msg, 60000)

// CORRECT — Clear handler in onDestroy
override fun onDestroy() {
    super.onDestroy()
    handler.removeCallbacksAndMessages(null)
}

4. Registering listeners without unregistering:

// WRONG
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    EventBus.getDefault().register(this)  // Never unregistered
}

// CORRECT
override fun onStart() {
    super.onStart()
    EventBus.getDefault().register(this)
}

override fun onStop() {
    super.onStop()
    EventBus.getDefault().unregister(this)
}

Detecting Memory Leaks

  • LeakCanary: Automatic leak detection in debug builds. Add debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12") to your dependencies.
  • Android Studio Profiler: Memory tab shows object count and heap dumps.
  • StrictMode: Detects leaked closeable objects and sqlite cursor leaks.

Rules to Prevent Context Leaks

  1. Never store Activity context in a static variable or singleton
  2. Use applicationContext for long-lived operations
  3. Use viewLifecycleOwner.lifecycleScope for coroutines in fragments
  4. Unregister listeners and callbacks in onStop/onDestroy
  5. Use WeakReference if you must hold a reference that shouldn't prevent GC

Context Best Practices

Context Best Practices

Choosing the Right Context

Use Case Context Why
Inflate layout Activity Needs theme for style resolution
Show dialog/alert Activity Needs window token
Start Activity Activity or Application Application works but activity gives better transition
Access resources Any Application is fine
Database Application Long-lived, no UI needed
Singleton/Service Application Prevents activity leak
Glide/Picasso Activity (or Application) Image libraries handle lifecycle

ContextWrapper Pattern

You can wrap a context to modify behavior without subclassing:

// Custom context wrapper for theming
val themedContext = object : ContextWrapper(baseContext) {
    override fun getResources(): Resources {
        // Modify resources behavior
        return super.getResources()
    }
}

Context in View Constructors

When creating custom views, use TypedArray from the context to read XML attributes:

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    init {
        val typedArray = context.obtainStyledAttributes(
            attrs, R.styleable.CustomView, defStyleAttr, 0
        )
        val color = typedArray.getColor(R.styleable.CustomView_customColor, Color.BLACK)
        val size = typedArray.getDimension(R.styleable.CustomView_customSize, 0f)
        typedArray.recycle()
    }
}

Testability and Context

Avoid passing Activity context directly to ViewModels or repositories. Use dependency injection to provide what's needed:

// Instead of passing context everywhere
class UserRepository(private val context: Context) { ... }

// Inject only what you need
class UserRepository(private val userDao: UserDao) { ... }

This makes testing easier — you can mock the DAO without needing a real context.

Quiz

1. What is the primary difference between Activity context and Application context?

Question 1 options

2. Why does storing Activity context in a singleton cause a memory leak?

Question 2 options

3. When should you use applicationContext?

Question 3 options

4. How does LeakCanary help with Context leaks?

Question 4 options

Flashcards

Question

What is Android Context?

Answer

An interface providing access to application resources, system services, and operations. Activities, Services, and Application are all Contexts.

Question

When should you use applicationContext over Activity context?

Answer

For singletons, database initialization, and any long-lived operation. Never use Activity context in objects that outlive the activity.

Question

What is the most common cause of Context memory leaks?

Answer

Holding a reference to an Activity after it's destroyed — e.g., static variables, singletons, unregistered callbacks.

Question

Can you show a dialog with Application context?

Answer

No. Dialogs require a window token, which only Activity context provides. Application context has no window.

Revision Notes

Key Takeaways

  • 1. Context is your app's handle to the environment — resources, services, and system operations
  • 2. Activity context has UI awareness; Application context does not
  • 3. The #1 memory leak is holding Activity context after the activity is destroyed
  • 4. Use applicationContext for singletons and long-lived operations
  • 5. LeakCanary automatically detects Activity context leaks in debug builds

Interview Tips

  • Explain what Context provides and why it exists
  • Know when to use Activity vs Application context for each scenario
  • Be ready to draw a memory leak diagram with Activity and singleton
  • Discuss how to test code that depends on Context using dependency injection

Cheat Sheet

Context Cheat Sheet

What Context Provides:

  • Resources (strings, drawables, colors)
  • System services (LayoutInflater, ConnectivityManager)
  • File and database access
  • Starting activities and services
  • Package information

Activity vs Application Context:

  • Activity: has window, theme, UI state
  • Application: no window, app-wide, long-lived

Memory Leak Rules:

  1. Never store Activity context in static/singleton
  2. Use applicationContext for long-lived operations
  3. Unregister callbacks in onStop/onDestroy
  4. Use viewLifecycleOwner.lifecycleScope for coroutines
  5. Use LeakCanary to detect leaks

When to Use What:

  • Dialog/Toast → Activity
  • Database/Singleton → Application
  • Inflate layout → Activity
  • Start Activity → Either (prefer Activity)