Flutter Theme Management with Clean Architecture

Murat Gun
Modanisa Engineering
3 min readAug 19, 2021

The theme is one of the indicator of the user-friendliness of a mobile application. Newly released applications are not considered very important and there is usually only one theme, but this is the wrong approach. Users want to customize the applications according to their own tastes, and they do this by choosing a theme in the easiest way. Today, I will tell you how you can manage themes with clean architecture in a Flutter application.

Photo by Mateusz Wacławek on Unsplash

ARCHITECTURE

Simply, in the architecture I use, the ThemeManager class provides the whole theme management. I’m using an enum to check for theme changes. I am listening for changes on MaterialApp using Provider package.

provider: ^6.0.2

IThemeManager Class

This class is an abstract class to create a draft for ThemeManager class. The same structure will work without creating this class, but it is important to use an abstract class in order to be suitable for layered architecture.

ThemeManager Class

This class is our base management class for theme. We provide all theme-specific management with this class. Instant theme information is kept on ThemeEnum in the enum structure. When this value is entered as a parameter to the generateTheme() function, the function returns a widget of type ThemeData, which is the widget that contains the Theme features in Flutter.

In case of a theme change, the changeTheme() function is triggered by the user. This action replaces the instant theme enum value with that of the user selected theme. This change is listened by Change Notifier and forwarded to MaterialApp.

Provider on ThemeManager

I use provider to listen for theme changes because it seems to me the most logical choice. After all, I’m listening to the status of a single value, it should be a light solution, and I’m listening on a class that has a lazy singleton structure, so it would be ridiculous to use it as a controller or viewmodel. The easiest way to listen for changes in this class directly is to use the Provider package. After extending the changeNotifier to my ThemeManager class, I just need to listen to the changeTheme() function.

If you ask why I use MultiProvider. In this project, I do not only the theme, but also a few other managements with the provider package. That’s why I used MultiProvider.

MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ThemeManager.instance),
],
child: ThemeManagementApp(),
);

ThemeContextExtension

I love using extensions in Flutter, this is one of them. This extension gives BuildContext the ability to listen for theme changes. Thanks to this extension, it is sufficient to simply write context.theme to the theme value in the MaterialApp widget. Also, since I call the ThemeData data as get, I gain a little bit of performance.

And you can use that extension in MaterialApp Widget like below.

CustomThemes

Finally, what I need is of course new theme data. We should create this data under ThemeData widget.

I almost forgot. You can also generate theme types from an abstract class. In this way, you will have the ability to manage all themes from a single source, especially in systems where you have multiple themes.

PANACHE

As you know, ThemeData class has so many fields and it’s hard to enter all values as manually. So, thanks to Panache, Panache is a Flutter Theme editor and we can select our application colors and fonts at Panache web site and Panache gives us ThemeData class of our application.

--

--