The Flutter GetX Ecosystem ~ State Management

Aachman Garg
Aug 30, 2020 · 7 min read

Flutter is awesome! It’s by far the fastest way to create truly cross platform apps without compromising beauty, performance and features. With development experience unlike any other framework, it does tick most of the boxes. However, it’s not perfect. There are some things that slow down the development from time to time.

Take for example, the boiler plate while implementing BLoC pattern or the time consumed by code generator in MobX or even the extra long syntax of Navigator and MediaQuery. All this hits the overall development experience with more lines of code and less efficiency.

Enter GetX!

GetX is a micro-framework that aims to provide top notch development experience by minimizing the boiler plate combined with neat syntax and simple approach. When developing with GetX, everything feels self evident and practical. It’s a solid blend of simplicity and power. It’s one of those rare packages that try to do everything and actually do it.

GetX provides a combination of State Management, Dependency Injection and Route Management solutions that work great together. But things don’t end here, it provides a ton of utilities that make it easy to implement internationalization, theming, validation, etc.

All of these solutions and utilities are packed in individually compiled containers which gives us the freedom to choose what to use and what not to, without compromising performance. However, once you’re using GetX, it’s hard to not use everything this package has to offer, because everything works so seamlessly together. And, that’s what I call The GetX Ecosystem.

What’s so special?

  • Firstly, I love the syntax! Before I used GetX, I couldn’t imagine that things like navigating to a route can be made this simple. We don’t need , builder or anything. Just write and that's it. And that's just one example.
  • Primary focus is on performance. Normally, we would have to choose which controllers to dispose and manually dispose them. With GetX, it’s the opposite. We have to choose which one to keep in the memory as they are disposed automatically. Saves memory, and lines of code.
  • 100% Decoupling! With GetX, it’s actually possible to achieve this. Business logic is separated from views, and even dependencies can be separated using something called Bindings.
  • It just works. Working with GetX is quite a satisfying experience. Whenever I’ve to implement a certain feature, there’s always a simpler way to do it with GetX, no matter the use case.
  • It’s well maintained and up-to-date. It can be challenging to keep all your packages updated and in sync with each other. Sometimes, there are breaking changes and things can get nasty. GetX centralizes most of our development needs under one package, so we don’t need to worry about compatibility and maintenance.

State Management? State Management!

State Management is still the hottest topic in Flutter Community. There are tons of choices available and it’s super intimidating for a beginner to choose one. Also, all of them have their pros and cons. So, what’s the best approach? Answer is simple — The one you feel comfortable with. Can GetX be the one? Let’s take a look!

GetMaterialApp

Step 0 : Use instead of .

Boom! Now you’re officially in the ecosystem.

Note: is optional if you’ll be using GetX only for state management, and actually used when managing routes, which we’ll cover in future articles.

GetxController

Controllers are classes where all our business logic goes. All the variables and methods are placed here and can be accessed from the view. While we can just create a simple class for this purpose, GetX provides a class called which extends .

This means that our controller will get deleted from memory as soon as the widgets using it are removed from the navigation stack. We don’t have to manually dispose anything and the memory consumption is reduced, resulting in high performance.

comes with and methods which essentially replace the and methods of the . This allows us to completely avoid using and write highly organized code.

GetBuilder

can be wrapped over any widget to make it interact with the methods and variables of the controller. We'll be able to call functions, listen to state changes, etc.

So, let’s create a controller first.

We use method inside any method in the controller so that our widgets can listen to the changes made by the method. If you have used Provider package, it's just like .

Now to make it work on the UI side, we wrap our widget with a .

You need to initialize only the first time it's used in . All other will automatically share the state of the first one, no matter where they are in the app.

essentially replaces the . You can keep all the pages and wrap specific widgets in . It's a nice way to manage ephemeral state, while keeping the code organized.

We also get a refined control over which widgets to update by assigning unique IDs.

GetX

is fast and has low memory footprint, but, it's not reactive. This means we'll be missing out on the power of streams. Well, for this very reason, (class) was created.

is very similar to in terms of syntax, but the approach is purely stream based.

Let’s see how it works:

Add to any variable and you make it observable. Basically you're turning into a stream of type . This means that we can listen to the changes made to counter from our view using .

is basically a without boilerplate.

is of type and to actually use it, we need to add to it. We have to do this with any kind of observable variable.

What if we want to make a class object observable? Well, it’s the same process. In one line of code, we can make all the variables of the class observable. Neat. I’ll show that while implementing .

Obx

This one is a personal favorite. It has the simplest syntax and implementation. All we’ve to do is wrap the widget in and we're done!

The syntax is shorter than , though there's one extra step here. We need to initialize the to use our variables and methods.

This is how we do it in GetX:

What’s happening here? Putting it this way makes the available in all the child routes of this class. We'll be able to get the same instance from anywhere in the app in a simple way. This will help us make multiple widgets interact with same controller in an organized way.

Now, to use the same instance in another class:

GetX will automatically find the instance we used previously, no matter where it is in the widget tree. Now, if we change the value of a controller variable from , it'll be updated in as well.

Which one to choose?

GetBuilder

  • When maintaining ephemeral state. Which basically means use it wherever you would use .
  • If performance is the top most priority. State is shared among builders and much RAM is not consumed.
  • If you don’t want to work with streams.

GetX

  • When you want the power of reactive programming.
  • It redraws the widget only when the value of variable is actually changed. Say value of variable is changed from to , then widgets will not be redrawn.
  • If you don’t want to instantiate controllers.

Obx

  • If you prefer a simple syntax.
  • If you’ll be using with multiple controllers in the same widget. doesn't need a type, so it can be used with any number of controllers. Something like this:
  • When using Bindings (we’ll discuss in the next article), always prefer

MixinBuilder

What?! There’s another one? Yes, there is. As the name suggests, it mixes two of the above approaches, which are and . With , we can use use and in the same widget.

Isn’t that cool? Why is it not discussed above? Well, because of two reasons:

  • It’s the heaviest of all other approaches, so will affect the performance in larger apps.
  • It has a very specific and rare use case, which we may never come across.

Still, if it works for you, go ahead and use it. Here’s the syntax!

What’s my approach?

For the most part, I use with Bindings as it allows the use of multiple controllers. For very simple widgets, where ephemeral state needs to change, I use .

For example, if a button changes it’s color, when pressed. In this case, working with streams will be an overkill, and natural choice would be . But our goal is to avoid using and keep business logic separated from view. is perfect for such use cases.

That’s it!

This was the GetX approach to State Management, which I feel is one of the best solutions out there. I hope this package and this article adds value to your Flutter development experience.

What’s next?

Here’s the link to GetX package: https://pub.dev/packages/get

Read Portuguese translation by Fábio Jansen

Read Spanish translation by mal2tin

Read Japanese translation by inari_sushio

Check out my previous work!

Any questions or suggestions? Put them all in the comments section :D

Liked the article? Press and hold on the 👏 button! That’ll motivate me to write more and more!

You can find me on LinkedIn, stalk my GitHub, follow me on Twitter or email me at imaachman@gmail.com for any kind of tech discussion.

Flutter Community

Articles and Stories from the Flutter Community