Flutter Freezed — The complete crash course
Introduction
Freezed is a code-generation package that helps you create data classes in Dart. It prevents you from writing hundreds of error-prone lines. Sometimes you just want a class that accepts its values in a constructor, a toString method and maybe value equality. That alone is a lot. But now imagine you want objects to remain immutable. For that you need an extra copyWith method. If you know how to implement all this in Dart, you surely know that it takes a many lines of code to achieve this. And that’s where freezed comes in…
Installation
First, you need to add the freezed
package to your dev_dependencies and add freezed_annotation
as a dependency. To generate code, we still need the build_runner
package in the dev_dependencies. Also, we want to use the package jsonn_serializable
in dev_dependencies as well as json_annotation
in dependencies to handle json easier (toJson and fromJson).
Here are all the commands you need:
flutter pub add freezed_annotation
flutter pub add dev:build_runner
flutter pub add dev:freezed
flutter pub add json_annotation
flutter pub add dev:json_serializable
Usage
First you need to create a class with the@freezed
or @Freezed()
annotation.
This now looks like this:
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass {}
Now you have to specify a super class that mixes in:
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass with _$MyDataClass {}
It may be that your linter shows problems. This is quite normal, and we will fix that soon.
Now we can get started on our first “feature”, which we discussed at the beginning. We want to create a constructor.
For this, we use a const factory
constructor, which points to a class with the same name as yours. The only difference is that this class has an underscore.
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass() = _MyDataClass;
}
Again, you don’t have to worry about your linter showing an error. This class does not exist yet, but will soon be generated by freezed.
Now you can specify in that constructor any field that you want. You don’t have to use the this.
syntax, because this part is handled by freezed.
Here is a small example you could use for authentication:
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass({
required int id,
required String email,
required String password,
}) = _MyDataClass;
}
But sometimes you need a default value. For example, if the user can eventually become a premium user, but is not one when the account is created. For this, you can use the @Default
Decorator:
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass({
required int id,
required String email,
required String password,
@Default(false) bool isPremium,
}) = _MyDataClass;
}
Very good! Now we have already created our constructor. Next we want to implement fromJson
.
import 'package:freezed_annotation/freezed_annotation.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass({
required int id,
required String email,
required String password,
@Default(false) bool isPremium,
}) = _MyDataClass;
factory MyDataClass.fromJson(Map<String, dynamic> json) => _$MyDataClassFromJson(json);
}
Again, we are using classes that have not been generated yet, so don’t worry!
Well, that alone was impressive! We created a full data class in 12 lines. However. We are now missing the copyWith() method or the toJson() method, right?
Well, not quite. Freezed does an incredible amount of work for us. It generates, without us doing anything, the following things:
toString()
method==
operatorhashCode
getter variablecopyWith()
methodtoJson()
method
At the latest, you can now understand why freezed is so helpful.
As a last step, we have to add onepart
declaration below the imports.
It’s this:part 'my_class.freezed.dart';
part
is "[...] a symptom for using library level privacy as opposed to class level privacy." (https://stackoverflow.com/questions/18403551/whats-the-reasoning-behind-part-and-part-of-in-dart-libraries)
import 'package:freezed_annotation/freezed_annotation.dart';
part 'my_class.freezed.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass({
required int id,
required String email,
required String password,
@Default(false) bool isPremium,
}) = _MyDataClass;
factory MyDataClass.fromJson(Map<String, dynamic> json) => _$MyDataClassFromJson(json);
}
Errors occur here as well, but you ignore them. These files have not been created yet, but we are doing that now.
Okay, now we get to the last step.
We now navigate inside the terminal to the folder of our project and execute the following command:
dart run build_runner build
.
Now you will find new files in your project.
Congratulations, you have now successfully built a data class in freezed!
How to update your data class
Now you want to change something. Let’s say in this example a part of the constructor. This is much easier than you think. First you just add a new field to your normal file. Let’s add a username:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'my_class.freezed.dart';
@Freezed()
class MyDataClass with _$MyDataClass {
const factory MyDataClass({
required int id,
required String username,
required String email,
required String password,
@Default(false) bool isPremium,
}) = _MyDataClass;
factory MyDataClass.fromJson(Map<String, dynamic> json) => _$MyDataClassFromJson(json);
}
The next step is to execute the command we just executed.
dart run build_runner build
That was easy, right?
Conclusion
In this article, you have learned the basics of the package freezed. You have seen how easy it is to use and how much time it saves you. We created a complete data class for authentication with 16 lines we wrote ourselves.
In the next few articles I will introduce more somewhat complicated packages and explain them. If you don’t want to miss this, I recommend you to follow me.
I really hope you enjoyed it! If so, I would be very happy if you could give this post some claps!
Thanks for reading, I wish you a great day and happy coding!
Sources to read more about freezed: