GetX is one of the popular state management package among the flutter developer. GetX is not just famous for high performances state management but the combination of intelligent dependency injection and route management also. So, It is the most liked packages with the likes of 7.56k as of now. As there are a lot of state management tools in flutter, GetX tops the list by being fast, stable, extra-light and powerful solution for flutter framework.
Related Read: Flutter Bloc: A Complete Guide
Why GetX is getting popular among the Flutter developers?
Developers are always trying to manage their application state in simple and well organized fashion while improving performances. GetX helps developers realize a high level of productivity through easy and pleasant syntax without sacrificing app performance. And GetX package helps the flutter developer to achieve it with these features:
High Performances
GetX is focus on high performance along with the minimum consumption of resources. Since, it doesn’t use Streams or ChangeNotifier.
High Productivity
Using simple and easy syntax, GetX will save hours of development and provide high performance. The developer should be careful about removing controllers from memory in general. This is not necessary with GetX because resources are automatically removed from memory when they are not in use. We must explicitly declare “permanent: true” in our dependent if we want it to be kept in memory. That way, in addition to saving time, we are less at risk of having unnecessary dependencies on memory.
Simple Code Organization
GetX helps to maintain the clean architecture by total decoupling of the View, presentation logic, business logic, dependency injection, and navigation. We do not need context to navigate between routes, so we are not dependent on the widget tree (visualization) for this.
Context is not required
In an application, context is very important since it is a link to the location of a widget in the tree structure of widgets. And sending the context from view to controller is tedious. But in GetX, we can access controllers within another controller without any context.
No code generation
While using other state management tools, we have to use the code generator (build_runner) after a slightly change on our code which is tedious and time consuming. But with GetX we don’t have to use the code generator at all.
Less Code
With GetX we don’t have to write boilerplate code like bloc pattern and other state management tools. Since we don’t have to create classes and event like bloc, we can achieve the high performances and productivity with much faster and less code.
Installing
Add Get to your pubspec.yaml file:
dependencies:
get:
Import get in files that it will be used:
import 'package:get/get.dart';
The generated code from the main.dart file by rendering Home is as follows:
import 'package:flutter/material.dart';
import 'package:getx_article/home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home(),
);
}
}
But to get started with the GetX, we have to replace the MaterialApp with the GetMaterialApp. This is because we can use GetX for Navigation. The GetMaterialApp is a class from the package.
Then our code with the GetX environment set up will be like:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_article/home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Home(),
);
}
}
Controllers
Before jumping into the GetX statemanagement, we must have knowledge about the controllers. Controllers are means to give control to the parent widget over its child state which contains all of your business logic for the application. This will make it easy to track different issues or errors. And GetX also contains the class called GetxController. We have to extend our controller from GetXController.
import 'package:get/get.dart';
class StateController extends GetxController{
// your state variables
//your methods
}
There are three popular methods which is also called lifecycle methods in the GetXController. They are onInit(), onClose() and onReady(). When your controller is created in memory, the onInit() method is called immediately, and the onClose() method is called when it is removed from memory. Soon after the widget has been rendered on the screen, the onReady() method will be invoked. Using this methods, we can replace the initState() and dispose() methods in StatefulWidget.
import 'package:get/get.dart';
class StateController extends GetxController{
@override
void onInit() {
// Here you can initialize and fetch you product from server
super.onInit();
}
@override
void onReady() {
// Called 1 frame after onInit(). It is the perfect place to enter
// navigation events, like snackbar, dialogs, or a new route, or
// async request.
super.onReady();
}
@override
void onClose() {
// Here, you can dispose your StreamControllers
// you can cancel timers
super.onClose();
}
}
StateManagement with GetX
There are two types of state managers with GetX. They are Simple State manager (Non-Reactive) and Reactive State manager. The main difference between them is Simple state manager updates the UI only when we want to whereas Reactive State manager data depends on stream and when the data changes all the listeners will update immediately.
Simple State Manager (Non-Reactive)
Non-Reactive state manager is simple state management in GetX which updates the UI only when we want to. The main point of using Simple state manager is to avoid the Streams and ChangeNotifier with uses of extremely low resources. So in order to listen the changes of state, update() method is used. We must call the update function after making changes to our state in our controller to tell the widgets that are listening to the state.
Let’s us see the example of counter increasing and decreasing:
import 'package:get/get.dart';
class SimpleStateController extends GetxController {
int _count = 0;
int get count => _count;
void increment() {
_count++; //for increasing the counter.
update(); //
for notifying the change in state.
}
void decrement() {
_count--; //for decreasing the counter.
update();
}
}
In the above code, update() function is called after each changes in the state.
For Simple state manager, GetBuilder is used to change the view based on the changing state.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_article/controller/state_controller.dart';
class Home extends StatelessWidget {
Home({Key? key}) : super(key: key);
final _controller = Get.put(SimpleStateController()); // dependency injection
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FloatingActionButton(
onPressed: () {
_controller
.increment(); //calling increment function from controller
},
child: const Icon(Icons.add),
),
FloatingActionButton(
onPressed: () {
_controller
.decrement(); //calling decrement function from controller
},
child: const Icon(Icons.remove),
)
],
),
appBar: AppBar(
title: const Text("GetX as State Management"),
),
body: GetBuilder<SimpleStateController>(
//GetBuilder is used to change the view based on changing state in GetX
init: _controller, //initializing the controller
builder: (controller) => Center(
child: Text(
"Count = ${_controller.count}",
//accessing the variable to change the UI from controller.
style: const TextStyle(
fontSize: 28, fontWeight: FontWeight.bold),
),
)),
);
}
}
Reactive State Manager
Using the update() method to listen after every changes in state is tedious. But in reactive state manager, our data depends on Streams. When data changes, all listeners will be notified right away. In order to do that in reactive approach, we need to create our variables observable. It helps to our widgets to keep track of changes in our variables and update on UI immediately. One of the method to convert the variables into reactive variables or observable variables is using GetX or ObX. Both of them is used as reactive state manager but GetX has lifecycle methods like init() and dispose() but ObX doesn’t.
Let’s us see the example of counter increasing and decreasing:
import 'package:get/get.dart';
class ReactiveStateController extends GetxController {
var _count = 0.obs; //Making the variable observable
int get count => _count.value;
void increment() {
_count++; //increasing counter
}
void decrement() {
_count--; //decreasing counter
}
}
In the above code, we make the variable reactive by adding .obs at the end of the variables. This way code became shorter as easy to read.
For Reactive state manager, Let us use the GetX to change the view based on the changing state. First replace the dependency injection with the ReactiveStateController as below.
final _controller = Get.put(ReactiveStateController()); // dependency injection
Then replace the GetBuilder in the home with the following code:
GetX<ReactiveStateController>( //GetX to change view based on changing state.
init: ReactiveStateController(), //initializing reactive state controller
builder: (controller) => Center(
child: Text(
"Count = ${_controller.count}", //accessing the variable to show changing count.
style: const TextStyle(
fontSize: 28, fontWeight: FontWeight.bold),
),
)),
);
ObX is lighter version of GetX. It is much more simple than GetX. We don’t have to initialize the Controller in ObX. we just have to wrap our widget from it.
Obx(() => Center(
child: Text(
"Count = ${_controller.count}",
style: TextStyle(fontSize: 28, fontWeight: FontWeight.w500),
),
)),
With the use of GetX package, we no longer need the StatefulWidgets in our application. we don’t need to waste our resources by making StatefulWidgets since, we can handle our UI state in simple and cleaner way using GetX or ObX than SetState.
If think otherwise about GetX? Read this article about Riverpod.