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.
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
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
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!
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.