DEV Community

Rebecca Franks
Rebecca Franks

Posted on • Updated on

Dark Mode Musings: Beware of the Context πŸŒ—

I’ve been working on getting Dark Mode in our app fully supported and I stumbled upon an interesting finding:

The Application#applicationContext does not keep information about the theme that you have set via AppCompatDelegate.setDefaultNightMode(), only a View or Activity context has this information stored.

After reading through Chris Banes’ articles and watching some great talks about Styles, Themes & Dark Mode, I felt pretty comfortable that I knew quite a bit about the Theming system on Android. However, this particular issue was something that I was not expecting, which is why I decided to document this particular problem I faced.

The Problem

I have the β€œDark theme” set on in my system settings, but inside my app I am explicitly setting the theme to light mode (even though my device theme is set to Dark):

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)

I have two bitmap resources: one located in drawable and one located in drawable-night.

Different Resources for Images

Despite my app theme overriding the mode to β€œlight”, the resource from drawable-night was loaded instead of the one from the drawable folder.

Incorrect Drawable Resource Loaded up for themes

Why was this happening? 🧐

I was using the Application#applicationContext to load up the Bitmap:

class BitmapLoader(val context: Context) {

    override fun loadBitmap(@RawRes resourceId: Int, bitmapConfig: Bitmap.Config): Bitmap? {
        val options =
            BitmapFactory.Options().apply { inPreferredConfig = bitmapConfig }
        return BitmapFactory.decodeResource(
            context.resources, resourceId, options
        )
    }
}
// This class was used in a similar way to the following usage:
val bitmapLoader = BitmapLoader(application.applicationContext)

The Solution

The fix in this case was to use the Activity#context method or View#context, instead of Application#applicationContext.

Correct background grid loaded up for theme

The lesson here is that the Application#applicationContext should not be used for retrieving UI resources. The Application object will only have system-level information and not information that is set by AppCompatDelegate. AppCompatDelegate only works on the activity-level.

You need to be very careful of the context you use when obtaining resources that could change based on the theme.

Thanks for reading, if you have any questions or comments β€” feel free to reach out on Twitter @riggaroo.

Thanks to Chris Banes and Alan Viverette for confirming what I was experiencing is intentional.

Top comments (0)