GetX State Management Flutter Tutorial

In this blog, we will explore the features of getx package. So let’s get started.

Introduction to GetX State Management

GetX is the most powerful, extra lightweight, high-performance framework for building flutter apps. It is the combination of state management, dependency injection, and route management. There are many state management libraries are available in the flutter like MobX, BLoC, Redux, Provider, etc. But, Getx has a simple syntax and anyone easy to use. In addition, it reduces the many boilerplate codes. We don’t need context for creating snack bars, dialogs, and bottom sheets and we don’t need StreamControllers and StreamBuilders.

Principles of GetX

The Getx has 3 principles. There are,

  • Performance
  • Productivity
  • Organization

Features of GetX

  • Easy Navigation
  • Snack bars, dialogs, and bottom sheets with no contexts
  • Easy state management
  • Easy dependency injection
  • Easy key/value storage
  • Easy change theme
  • Easy Validators
  • Easy internationalization

Installing GetX

To install the getx of visit the GetX official page on pub.dev and copy the latest version of the package. Then  Open pubspec.yaml file and add getx package in your dependency. Then don’t forget to run pub get, then only the package will add your project. 

dependencies:
   get: ^4.1.4

As of the time of writing this article, the current version of GetX is 4.1.4. It may change in feature. Please use the latest version. 

Alternatively, you can run the flutter pub add get command.

flutter pub add get

Now, import the package of your project.

import 'package:get/get.dart';

Then, Instead of using MaterialApp change it into the GetMaterialApp, Example Code given below,

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(                 
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

Getting Started With GetX

Now, we explore the features of getx one by one.

Route Management

In the old method, we use Navigator. Now we don’t need any lengthy code.

Navigation without named routes

Navigate to a new screen:

Get.to(NextScreen());

To close snack bars, dialogs, bottom sheets, 

Get.back();

This method is used to go to the next screen and remove the previous screen. This method is helpful when we use SplashScreens, login screens and etc.

Get.off(NextScreen());

This method is used to go to the next screen and remove all previous routes. This method is useful when we use shopping carts, polls, and tests, etc.

Get.offAll(NextScreen());

Navigation with named routes

If you prefer navigation with named routes you can these methods. Initially, we need to define the routes,

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => Second()),
        GetPage(
          name: '/third',
          page: () => Third(),
          transition: Transition.zoom  
        ),
      ],
    )
  );
}

Navigate to a new screen with a name.

Get.toNamed('/details');

This method is used to go to the next screen and remove the previous screen. This method is helpful when we use SplashScreens, login screens and etc.

Get.offNamed("/NextScreen");

This method is used to go to the next screen and remove all previous routes. This method is useful when we use shopping carts, polls, and tests, etc.

Get.offAllNamed("/NextScreen");

If any route is missed, that makes a 404 error. To handle the non-defined routes, we can use the unknown route.

void main() {
  runApp(
    GetMaterialApp(
      unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => Second()),
      ],
    )
  );
}

Navigation without context

In getx, we don’t need any context for creating snack bars, dialogs, and bottom sheets.

SnackBars

Get.snackbar('Hi', 'i am a modern snackbar');

Dialogs

Get.dialog(YourDialogWidget());

BottomSheets

Get.bottomSheet(
  Container(
    child: Wrap(
      children: <Widget>[
        ListTile(
          leading: Icon(Icons.music_note),
          title: Text('Music'),
          onTap: () {}
        ),
        ListTile(
          leading: Icon(Icons.videocam),
          title: Text('Video'),
          onTap: () {},
        ),
      ],
    ),
  )
);

State Management

Getx has two different state managers. They are,

  1. Simple State Manager (GetBuilder)
  2. Reactive state manager (GetX/Obx)

Simple State Manager (GetBuilder)

In Simple State Manager, it updates only the required widgets and the state manager uses less memory(~ 0MB). It does not need a change notifier.

First, create a controller class and extends GetxController. Then write your method/function and use update() to update the counter variable on UI.

class Controller extends GetxController {
  int counter = 0;
  void increment() {
    counter++;
    update();
  }
}

In Getx, you don’t need a stateful widget. Wrap your existing widget as GetBuilder and give the Controller a parameter. Then initialize the controller using the init property. In the builder property, give your widget. The sample code is given below,

GetBuilder<Controller>(
  init: Controller(), // INIT IT ONLY THE FIRST TIME
  builder: (_) => Text(
    '${_.counter}',
  ),
)

Note: Initialize the controller only one time. Don’t initialize the same controller in another place. In second-time use ReBuilder for the same controller.

Reactive state manager (GetX/Obx)

In Reactive State Manager you don’t need any StreamControllers, StreamBuilders, and other stuff.

Simply create a variable,

var name = 'Shibu';

Make it observable. To make it observable, simply add the “.obs” end of it.

var name = 'Shibu'.obs;

Update the variable as per your need,

name.value='Code With Flutter';

To update the UI as dynamic, wrap your existing widget as Obx. Example code is given below,

Obx(() => Text("${controller.name}"));

That’s all. It’s that simple.

For Example of Reactive State Manager,

class Controller extends GetxController{
  var count = 0.obs;
  increment() => count++;
}
class Home extends StatelessWidget {
  @override
  Widget build(context) {
    final Controller c = Get.put(Controller());
    return Scaffold(
      appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
      body: Center(child: ElevatedButton(
              child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
      floatingActionButton:
          FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  }
}
class Other extends StatelessWidget {
  final Controller c = Get.find();
  @override
  Widget build(context){
     return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

Dependency Management

One of the main features of Getx is simple and powerful dependency management. So we don’t need Provider context and inheritedWidget.

Instancing methods

To implement the dependency injection, there are four types of methods are available.

  1. Get.put()
  2. Get.lazyPut
  3. Get.putAsync
  4. Get.create
Get.put()

The Get.put() method is the most common way of injecting dependency. For Example,

Controller controller = Get.put(Controller());

To keep the dependency as an entire session, you can add the permanent property as true. For Example,

Get.put<LoginController>(LoginController(), permanent: true);
Get.lazyPut

 It will be instantiated only when is used. For Example,

Get.lazyPut<Controller>(() => Controller());
Get.putAsync

If you want to use an asynchronous instance, you can use Get.putAsync.

Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() );
Get.create

It creates a new instance of the dependency every time Get.find is called.

Get.Create<SomeClass>(() => SomeClass());
Get.Create<LoginController>(() => LoginController());

Using instantiated methods/classes

To use the injected dependency in another class, you can use Get.find() method. For Example,

final controller = Get.find<Controller>();
// OR
Controller controller = Get.find();

For more information about getx visit official documentation.

%d bloggers like this: