Photo by Clément H on Unsplash

About Context, Themes, and traps

As Android Engineers, we are well aware of Context, its duties and its limitations, but there is often no reason to use a subclass to fetch resources. Apart from themes (which we know heavily depend on what Context they receive when we want to style something), it’s usually safe to use the superclass. For certain, I wouldn’t have ever thought that system light or dark mode could actually affect a drawable. But let’s take a step back.

The bug

Let’s suppose we have 2 versions of the same icon, one for light mode painted with yellow color, and one for dark mode painted in blue.

Furthermore, we want to manage the light to dark mode switch manually inside the app by using the AppCompatDelegate:

This was made so users can freely change their theme based on their needs or wishes, and we foresee the app UI can only be in one of these two states:

And until Android 10, this was the case. Unfortunately, with Q, we noticed that we could end up in two unforeseen states:

After a little bit of digging, I noticed that the images were switched according to the system’s mode: if the system was in dark mode, the selected bucket would be the night one, regardless of the theme specified in the Activity.

The solution

It took me several attempts to understand what was causing this issue. Since the icons are placed in the Toolbar, I tried in multiple ways to set a different ContextThemeWrapper but, even if I was on the right path, nothing changed.

For reference, the code that was used to dynamically load icons inside the Toolbar was very similar to the following snippet:

I stared at the same lines for a couple of hours, but the solution was right in front of me: the issue I was facing was related to the theme, so we should have used the right Context to load the images. With a deeper look, I noticed resources was pulled from Application: this could definitely be causing the issue!

Replacing resources with activity on line 6 did the trick, and the icons were loaded as expected, and it all went down to that.

Today I learned

A theme does not only affect the colors, but also the bucket from which the app is taking the images, especially if the version of Android supports a system-wide light/dark mode switch. Using the wrong Context will change the effect on the UI, and the app will think it is loading the resources based on the system status. This theme might not be aligned with the one used in the app, especially if the latter is not following the light/dark mode on the system.

If you want to play with around with this behavior, feel free to reach the sample on GitHub.

Thanks to Daniele Bonaldo, Fabio Collini, Sebastiano Gottardo and Omar Miatello for proofreading this post.

Android developer and GDE for Android

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Roberto Orgiu

Roberto Orgiu

Android developer and GDE for Android

More from Medium

Fused Location Provider in Kotlin

Swipe to delete in Jetpack Compose Lazy Column Android

Collect Kotlin’s Flow Lifecycle Aware With Style

An image of a waterfall.

Build Single Activity Apps With Jetpack Compose

Hand holding an android device