Flutter GetX: Where Does Get.put Go in a Widget?
Asked Answered
K

5

7

I am new to GetX and am trying to learn how to use it. I have read different tutorials that inject the controller outside of the widget's build method, and others that put it inside it.

class MyWidget extends StatelessWidget{
  const MyWidget({Key? key}) : super(key:key);

  //Outside...
  final controller = Get.put(Controller()); //<---

  @override
  Widget build(BuildContext context) {
    //Inside...
    final controller = Get.put(Controller()); //<---

    return Obx(
      () => Text(controller.name)
    );
  }
}

Is there a difference between those two locations? If so, why?

Also, where should it go in a StatefulWidget? It seems it should not go inside the build method because it causes a stack overflow error for me.

Does the location of Get.put() matter inside a widget?

Kamseen answered 27/8, 2022 at 6:44 Comment(0)
D
4

The normal way is to put the controller outside the widget, so it will be created once. if you but it inside the widget a new instance of the controller will be created each time you refresh (update) the widget. Also, with GetX there is no need to use StatefulWidget.

Dasilva answered 27/8, 2022 at 10:12 Comment(0)
K
3

The answers shared are correct. Thank you! I wanted to post another answer that I consider to be an even better way to do it as referenced in the documentation.

This method allows for controller access without ever putting Get.put in any of your widgets. This is also really helpful if you have a lot of controllers and need to reference them in widgets as well as from other controllers.

Here is an example:

//ControllerA
class ControllerA extends GetxController {
  static ControllerA get to => Get.find();

  final name = 'Bob'.obs;

  someMethod(){
    ControllerB.to.anotherMethod(); //'I am inside ControllerB!'
  }
}

//ControllerB
class ControllerB extends GetxController {
  //+++
  static ControllerB get to => Get.find();

  anotherMethod(){
    print('I am inside ControllerB!');
  }
}

And then inside Widgets:

class MyWidget extends StatelessWidget{
  const MyWidget({Key? key}) : super(key:key);

  @override
  Widget build(BuildContext context) {

    return Obx(
      () => Text(ControllerA.to.name) //Bob
    );
  }
}

This requires that you add your Get.put declarations in main.dart so that you make sure they are all ready:

void main() {
  Get.put(ControllerA());
  Get.put(ControllerB());

  runApp(
    GetMaterialApp(...)
  );
}

In my opinion, it's really clean like this--and very convenient!

Kamseen answered 28/8, 2022 at 0:27 Comment(1)
Great answer! Helped me to clean up the code so much.Lillie
M
2

If we want to keep a GetX controller in memory forever, then we should indeed instantiate it outside of a Widget's build() function (such as within main() as Clifton shows).

(Note that we can also use GetXService for persistent controllers, which allows manual disposal.)

Placing controllers inside build() functions, is the correct place when we want GetX to free memory & dispose the controller when the widget goes "out of scope". (e.g. when the user has "popped" the route from the stack.) There's also no danger in "recreating" the controller when its instantiated inside build(): Get checks for existence of a controller when Get.put() is called and skips it if the controller is already instantiated.

See this answer (and link to an explanation by one of Get's maintainers) for more info on why we should Get.put() inside build().

Melo answered 29/8, 2022 at 18:55 Comment(0)
F
1

When you put it inside the build method, it will create a new instance every time the widget is rebuilt, so it is better to but it outside and in most cases I think you do not need to use StatefulWidgetwith GetX even in animation.

Flan answered 27/8, 2022 at 10:27 Comment(0)
B
1

Based on @clifton-labrum answer. Read it first.

Controller Sample :

//ControllerA
class ControllerA extends GetxController {
  static ControllerA get to {
    try{
      return Get.find<ControllerA>();
    } catch (e){
      return Get.put(ControllerA());
    }
  }

  final name = 'Bob'.obs;
}

Widget Sample :

class MyWidget extends StatelessWidget{
  const MyWidget({Key? key}) : super(key:key);

  @override
  Widget build(BuildContext context) {

    return Obx(
      () => Text(ControllerA.to.name) //Bob
    );
  }
}

Implementing this way you don't need to declare anything on main.dart.

Bridie answered 25/3 at 9:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.