Equatable in Flutter: A Complete Guide
What is Equatable? How to use it? What's the difference between using ( == & hashcode ) vs. ( Equatable )
Comparing Two Objects in Manual Way
- While developing the Flutter application, we often wanted to compare two objects and check whether they are equal or not.
- To do that, dart provides two methods
==andhashcode. - By
overridingthese methods we can compare our instances. - Let's take an example and compare two objects by overriding these two methods.
- Example: Comparing Two Car Objects Example
Car.dartclass Car { final String carName; final String carImage; const Car({required this.carName, required this.carImage}); }- In
main.dartI've created twoCarobjects final Car audi = Car(carName: "Audi", carImage: "assets/images/audi.png"); final Car bmw = Car(carName: "BMW", carImage: "assets/images/bmw.png");- UI of Car
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.amber, body: Center( child: Container( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CarWidget( carImage: audi.carImage, carName: audi.carName, ), SizedBox( width: 200, height: 50, child: ElevatedButton( onPressed: () { compareObjects(context); }, child: Text("Compare"), ), ), CarWidget( carImage: bmw.carImage, carName: bmw.carName, ), ], ), ), ), ); } }- Output :

Now Let's implement
Comparefunction :compareCars(BuildContext context) { if (audi == bmw) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("YES, They are EQUAL"))); } else { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("NO, They are not EQUAL"))); } }- Call this function in
Comparebutton ElevatedButton( onPressed: () { compareCars(context); }, child: Text("Compare"), ),- Now if we try to compare these two objects, we'll get
NO, They are not EQUALScaffold message 
- This seems fine
- But now let's create two same cars and compare :
// Creating two same car final Car audi = Car(carName: "Audi", carImage: "assets/images/audi.png"); final Car audi2 = Car(carName: "Audi", carImage: "assets/images/audi.png");
- Now if we compare
audiandaudi2, what should be the output according to you?. Let's check!! compareCars(BuildContext context) { if (audi == audi2) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("YES, They are EQUAL"))); } else { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("NO, They are not EQUAL"))); } }Output

Strange ๐ค!! It's still giving a They are Not Equal message. It's because under the hood Dart doesn't compare the objects by their value.
- Here the
audiandaudi2both objects are in different memory locations. It doesn't matter if they have exact same values. They both will be considered as different objects. - So what we can do now?
- Well, Dart provides us two methods that we can override.
==andhashcodemethods. - Let's implement those two methods in our
Car.dartmodel class. class Car { final String carName; final String carImage; const Car({required this.carName, required this.carImage}); @override bool operator ==(Object other) => identical(this, other) || other is Car && runtimeType == other.runtimeType && carName == other.carName && carImage == other.carImage; @override int get hashCode => carName.hashCode ^ carImage.hashCode; }- What this
==method do is, It will compare objects by theirtype, andvalues. - Now if we click on the Compare button -

- It's Working. But the problem is you have to compare each and every field of your model class manually in the
==method and also within thehashcodemethod. - You can see how this can quickly become a hassle when dealing with complex classes. This is where
Equatablecomes in!
Using Equatable
- The
Equatablesimplify the above process by overriding==andhashcodefor you. - Let's install
equatablepackage equatable: ^2.0.3- Now all you have to do is to extend your class with Equatable and override a getter method
props. import 'package:equatable/equatable.dart';class Car extends Equatable { final String carName; final String carImage; const Car({required this.carName, required this.carImage}); @override List<Object?> get props => [carName, carImage]; }propsis a getter method that will returnList<Object>. HereObjectcan be of any type (like :int,double,listetc). You have to simply return a list of all the objects that are available in your class (carNameandcarImagein our case).- THAT'S IT !!!!!!

Note: Equatable is designed to only work with immutable objects so all member variables must be final
EquatableMixin :
- If your class is already extending anything then you can use
EquatableMixinmixin. class Car extends Object with EquatableMixin { final String carName; final String carImage; const Car({required this.carName, required this.carImage}); @override List<Object?> get props => [carName, carImage]; }
Equatablealso provide one additional functionality i.estringifymethod.- If you want to override
toStringmethod simply override thestringifymethod - class Car extends Object with EquatableMixin { final String carName; final String carImage; const Car({required this.carName, required this.carImage}); @override List<Object?> get props => [carName, carImage]; @override bool get stringify => true; }- This will override
toStringmethod with all the fields which we have in our class.
- Thank you for reading. See you in the next article
- Comments and Feedbacks are welcomed ๐
- Until then ....

ย

