What's the best practice to keep all the constants in Flutter?
What's the best programming practice to
create a constant class in Flutter
to keep all the application constants for easy reference. I know that there is const
keyword in Dart for creating constant fields, but is it okay to use static
along with const, or will it create memory issues during run-time.
class Constants {
static const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";
}
My preferred solution is to make my own Dart library.
Make a new dart file named constants.dart
, and add the following code:
const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";
Edit: 99% of the time you don't need to explicitly name your dart libraries with a statement like library library_name;
at the top of your file, and you probably shouldn't (reference).
Even if you leave out this line your file will still be library! It will just be implicitly named.
Then add the following import statement to the top of any dart file which needs access to the constants:
import 'constants.dart' as Constants;
Note if constants.dart
is in different directory then you will need to specify the path to constants.dart
in your import statement.
EDIT: Use lowercase_with_underscores
when specifying a library prefix.
In this example:
You could use a relative path:
import '../assets/constants.dart' as constants;
Or an absolute path from the lib directory:
import 'package:<your_app_name>/assets/constants.dart' as constants;
Now you can easily access your constants with this syntax:
String a = Constants.SUCCESS_MESSAGE;
EDIT
Now that the flag --dart-define
has been added to the different command lines of Flutter, the following answer no-longer applies.
Instead just declare constants wherever you want, and potentially refer to other answers.
While there are no technical issues with static const
, architecturally you may want to do it differently.
Flutter tend to not have any global/static variables and use an InheritedWidget.
Which means you can write:
class MyConstants extends InheritedWidget {
static MyConstants of(BuildContext context) => context. dependOnInheritedWidgetOfExactType<MyConstants>();
const MyConstants({Widget child, Key key}): super(key: key, child: child);
final String successMessage = 'Some message';
@override
bool updateShouldNotify(MyConstants oldWidget) => false;
}
Then inserted at the root of your app:
void main() {
runApp(
MyConstants(
child: MyApp(),
),
);
}
And used as such:
@override
Widget build(BuilContext context) {
return Text(MyConstants.of(context).successMessage);
}
This has a bit more code than the static const
, but offer many advantages:
- Works with hot-reload
- Easily testable and mockable
- Can be replaced with something more dynamic than constants without rewriting the whole app.
But at the same time it:
- Doesn't consume much more memory (the inherited widget is typically created once)
- Is performant (Obtaining an InheritedWidget is O(1))
Referring to https://dart.dev/guides/language/effective-dart/design
It's a good practice to group, constants and enum-like types in a class like below:
Auto import is straightforward in Android Studio, where you can type the class name Color, and Android Studio will be able to suggest auto import of Color class.
I've noticed a little confusion across the answers here, so I thought I would try to clear a few things up.
Dart/Flutter guidelines suggest not creating classes that only contain static members, namely because it isn't necessary. Some languages, such as Java or C# will not allow you to define functions, variables, or constants outside of a class, but Dart will. Therefore, you can simply create a file such as constants.dart that contains the constants that you want to define.
As noted by @Abhishek Jain, the library
keyword is not required for this method to work. The library
keyword is used for libraries that will be published for use in other projects, although it can be used along with part
and part of
to break a single library up across multiple files. However, if you need that, then your needs are probably beyond the scope of OP's question.
As pointed out by @ChinLoong, it is technically acceptable to create a class that groups related constants and enum-like types. It should be noted however that this demonstrates an exception to the guideline as it is not a hard rule. While this is possible, in Dart, it is frowned upon to define a class that is never instantiated. You'll notice that the Dart Color class that defines Color constants has a constructor which excepts an integer value, allowing instantiation for colors not defined by a constant.
In conclusion, the approach that best adheres to the Dart guidelines is to create a constants.dart file or a constants folder containing multiple files for different constants (strings.dart, styles.dart, etc.). Within the constants.dart file, define your constants at the top level.
// constants.dart
const String SUCCESS_MESSAGE=" You will be contacted by us very soon.";
...
Then, import
the file wherever the constants need to be used and access directly via the constant's name.
That's completely up to you.
Using static has no disadvantages.
Actually const
is required for fields in a class.