Getx: Controller is not deleted at the appropriate timing.

Created on 26 Jan 2021  Â·  2Comments  Â·  Source: jonataslaw/getx

Describe the bug
onClose is not called at appropriate timing. So, controller is not deleted when it is not used.


Reproduction code

  • main.dart
void main() {
  // navigation order
  // HomeScreen --> NestedScreen --> NestedOne
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: HomeScreen(),
    );
  }
}
  • home_screen.dart
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('HomeScreen'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.to(NestedScreen());
                  },
                  child: Text('Go to Nested Screen')),
            ],
          ),
        ),
      ),
    );
  }
}
  • nested_screen.dart
class NestedScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Nested Screen'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.back();
                  },
                  child: Text('Return to Home Screen')),
              ElevatedButton(
                  onPressed: () {
                    Get.to(NestedOne());
                  },
                  child: Text('Go to 1st Screen')),
            ],
          ),
        ),
      ),
    );
  }
}
  • nested_one.dart ( Controller is used only NestedOne)
class NestedOne extends StatelessWidget {
  // Controller is used only here
  final Controller _c = Get.put(Controller());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Nested One'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.back();
                  },
                  child: Text('Return to Nested Screen')),
            ],
          ),
        ),
      ),
    );
  }
}
  • controller.dart
class Controller extends GetxController {
  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onClose() {
    super.onClose();
  }
}

To Reproduce
Steps to reproduce the behavior:

  1. Click button and go to NestedScreen from HomeScreen.
  2. Click button and go to NestedOne from NestedScreen.
  3. Go back to NestedScreen from NestedOne.
  4. Go back to HomeScreen from NestedScreen.


Expected behavior
I expect Controller is deleted from memory at step 3, because Controller is only used at NestedOne. But Controller is deleted at step 4.


Screenshots

[GETX] "GetMaterialController" has been initialized
[GETX] GOING TO ROUTE /NestedScreen
[GETX] "Controller" has been initialized
[GETX] GOING TO ROUTE /NestedOne
[GETX] CLOSE TO ROUTE /NestedOne
[GETX] CLOSE TO ROUTE /NestedScreen
[GETX] "Controller" onClose() called
[GETX] "Controller" deleted from memory


Flutter Version:

Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (7 weeks ago) • 2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4

Getx Version:
3.24.0

Describe on which device you found the bug:
Pixel 2 XL API 30 - Android.

Most helpful comment

Hi @jintak0401,

When you use unnamed routes, you must use Get.put within the build function, when using it in a StatelessWidget

class NestedOne extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final Controller _c = Get.put(Controller());   // here
    return Scaffold(
      appBar: AppBar(
        title: Text('Nested One'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.back();
                  },
                  child: Text('Return to Nested Screen')),
            ],
          ),
        ),
      ),
    );
  }
}

All 2 comments

Hi @jintak0401,

When you use unnamed routes, you must use Get.put within the build function, when using it in a StatelessWidget

class NestedOne extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final Controller _c = Get.put(Controller());   // here
    return Scaffold(
      appBar: AppBar(
        title: Text('Nested One'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                  onPressed: () {
                    Get.back();
                  },
                  child: Text('Return to Nested Screen')),
            ],
          ),
        ),
      ),
    );
  }
}

Thank you very much, @eduardoflorence!

As you told I use Get.put in build function, it works correctly. With named routes, it also work correctly. Thank you :)

Was this page helpful?
0 / 5 - 0 ratings