Don't copyWith a ThemeData in Flutter

Published 06.06.2022 • Last modified 24.09.2023

While reading the code of flutter apps, I’ve seen this particular piece of code repeated way too many times:

return MaterialApp(
  theme: ThemeData.dark().copyWith(
    textTheme: ...
  ),
  home: ...
)

This is problematic for a couple reasons that become clear when we take a peek at how ThemeData works.

This is taken directly from the material library’s code:

factory ThemeData.dark() => ThemeData(brightness: Brightness.dark);

That is all that it does. It just changes the brightness parameter from light to dark. What does the source code for copyWith look like? Well, you can take a look for yourself.

All this class-constructing parameter-passing is unnecessary work that could be easily avoided.

There’s another problem with this approach too. The default ThemeData constructor provides useful information on some of the parameters, but copyWith replaces it with less helpful documentation.

Creates a copy of this theme but with the given fields replaced with the new values

How to use ThemeData correctly #

return MaterialApp(
  theme: ThemeData(
    brightness: Brightness.dark,
    textTheme: ...
  ),
  home: ...
)

Instead of copying ThemeData.dark(), we’re just providing a brightness to the default factory. The correct values will be calculated from the brightness just like before. One disadvantage with this method is that it might be less readable. For this reason, you should always put the brightness first, before the other arguments.