Color and Style: global const vs theme
I searched for Flutter articles today and found Derrit Mwiti’s article with the Title ‘Flutter Development Best Practices’. I’m learning flutter since January 2020 and think it’s crucial not to get used to bad habits. Therefore such articles are very interesting for me. Most of the practices recommended by Derrit I can understand. But the first one in his list made me doubt.
Are themes really that great?
He begins with the advice to use themes and points out the following advantages:
- It’s easier to reference properties anywhere in the code
- It prevents code repetition
- It’s easier to adjust a property at one place and see the change everywhere.
Then he gives some code samples to show how the themes are defined and how they are used.
This is all well and good, but it occurred to me that all these advantages can also be achieved with simple global constants. I saw these globals first in the source code of Dane Mackier on github. In his project 014 he defines colors and fonts with global constants in files like app_colors.dart and textstyles.dart.
I found a similar practice in Angela Yu’s great flutter course on Udemy. She has a file called constants.dart, where all the textstyles are defined in one place.
So I asked myself the question: How can the pros and cons of these two practices be weighed up? Which is “better”?
Let’s first see whether the three advantages of the standard flutter theming are reached by global const.
It’s easier to reference properties anywhere in the code
This is even easier with global constants. The Intellisense popup lists all defined constants as soon as I enter the small k. This is a convention that is also used in Googles flutter and dart source code.
It prevents code repetition
This is also achieved. Define a constant once and use it anywhere.
It’s easier to adjust a property at one place and see the change everywhere.
This also applies here. If I adjust the global constant, all widgets that use it will change.
Are the even more advantages on the side of globals?
Well — in my opinion there are: It’s less code. And less is often more — right?
Typically a property is more often referenced than defined. So let us first look how properties are used.
For example a color:
and a text style:
In both cases the usage of a const value is shorter.
The definition of properties is — in my optionion — also easier. I remember having seen definitions of themes but can’t remember the exact syntax and the possible shortcuts with copyWith and so on.
Something like this example from Derrit:
I would define as:
const kStyleTitle = TextStyle(
fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.bold,
const Color kSliderColor = Color.fromARGB(0xff, 0xe1, 0x0c, 0x35);
The TextStyle is just a copy&paste from the style property of a Text widget. So there is nothing special to remember.
One more advantage is that the constants file contains all used fonts and colors of the app in one place. On the other side the theme will provide all the standard settings plus maybe some additional custom properties. So it’s higher risk to use an unintended default fontstyle.
And what about the runtime performance?
I expect the simple use of a constant takes less cpu cycles than looking up a value in the widget tree by the Theme.of(context) call.
So what’s the catch?
After this outweigh of the advantages what are the disadvantages of global constants?
Well — global constants have a code smell. This is not easy to ignore.
But: I think it’s crucial in every domain to know when to break the rules.
The bad image of global objects is mainly due to two dangers:
- There is no control over whether such objects are changed anywhere unintentionally.
- Unexpected naming conflicts can occur, for example when an added plugin or updated library suddenly uses the same name.
The first risk does not really exist because, after all, they are constants. They can be considered as not changing.
The second risk is left. In this case, however, VS Code displays a very helpful error message.
After all, for me, global constants are OK. And there are some more reasons to use the globals without guilty conscience.
Number one reason is:
The flutter library provides also a lot of global const values.
From there comes the convention to start the names with the lowercase ‘k’.
A grep in Sublime Text results in 5 files with 35 matches when searching in files named constants.dart. And there are a lot more kNames shown in the Intellisense popup when you enter the ‘k’ and Ctrl+Space. The entries range from kAlwaysCompleteAnimation (defined als global const in animations.dart) to kZoomControlsTimeout in gestures/constants.dart.
A Second reason for me are the code examples of Dane Mackier. For me he is a role model with a lot of experience. I think he thought very thoroughly about his use of global constants. BTW: His articles on Medium and tutorials on his web site are great!
And last but not least is Angela Yu. She will have thought twice to use global constants when creating her course examples. This will influence a lot of future flutter developers. In her example app Flash-Chat she even defines the complete decoration of textfields as const values.
const kTextFieldDecoration = InputDecoration(
hintText: 'Enter a value',
vertical: 10.0, horizontal: 20.0),
color: Colors.blueAccent, width: 1.0),
or the decoration of containers:
const kMessageContainerDecoration = BoxDecoration(
color: Colors.lightBlueAccent, width: 2.0),
This example demonstrates one more advantage over using a theme: Such global constants can also be used for widgets. That makes sense if they are used more than once.
If you can’t live with global const
then wrap them as statics in a class like so:
String appName = "Flutter App"; static Color lightPrimary = Colors.white;
static Color darkPrimary = Colors.black;
and use them together with the class name:
barColor: isDark ? Constants.darkPrimary : Constants.lightPrimary,
I found this solution on github in the source of the FlutterEbookApp by Festus Babajide Olusegun. The usage is a bit more verbose, but you avoid the risc of getting clashes with already existing names in the global name space.
This article was just comparing flutter standard theming versus global constants. I prefer using a collection of global const in a single file, which I name app_constants.dart.
I’m thinking about collecting frequently used constants from all my apps in a common const template. In comparison to a collection of code snippets in the editor these collection would make the start of a new app much easier.
BTW: The other best practices of Derrit’s article are — in my opinion — recommendable.
Flutter is a young framework and quickly developing. Time will show which practices prevail. Maybe I oversee advantages of the theming. Maybe theming is superior in really big apps. If you have some more insights please add your remark to my article. It’s very welcome.