getxController isn't being disposed/deleted when it should be

Created on 29 Dec 2020  Â·  16Comments  Â·  Source: jonataslaw/getx

Describe the bug
when i go from screen 1 to screen 2 i expect the controller to be deleted/disposed but this doesn't happen. and you can see this as the timer completes from where it stopped.
i based my expectations on this document https://github.com/jonataslaw/getx/blob/master/documentation/en_US/state_management.md#simple-state-manager section How it handles controllers

Reproduction code

import 'dart:async';
import 'package:get/get.dart';
import 'package:flutter/material.dart';

runApp(sandbox());

dynamic sandbox()
{
  return GetMaterialApp(
        title: 'Getx issue',
        debugShowCheckedModeBanner: false,
        home: Prime()); 
}

class PrimeController extends GetxController {
  Timer _timer;
  Rx<Duration> recordedTime =  Duration.zero.obs;
  @override
  void onInit() {
    super.onInit();
    _timer = Timer.periodic(
        Duration(
          seconds: 1,
        ),
        (newVal) => recordedTime.value = recordedTime.value + Duration(seconds: 1)); 
  }

  @override
  void onClose() {
    _timer.cancel();
    //THIS IS NEVER HIT
    super.onClose();
  }
}


class Prime extends GetView<PrimeController> 
{
  Prime()
  {
    Get.put(PrimeController());
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: 
      Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
        Obx(()=>Text('${controller.recordedTime.value}')),
        _nextPage(),
      ],)
    ,),
    );
  }
  Widget _nextPage()
  {
    return RaisedButton(onPressed: ()=>Get.off(SomePage()),child: Text('Next page'),);
  }
}


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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("SomePage"),),
      body: Center(
      child: RaisedButton(child: Text("Previous page"),onPressed: ()=>Get.off(Prime())),
    ),
    );
  }
}

To Reproduce
Steps to reproduce the behavior:

  1. press 'Next page' button
  2. press "previous page" button
  3. notice the error (the timers completes from where it stopped)

Expected behavior
the timer should reset as the controller was disposed and rebuilt

Screenshots
none

Flutter Version:
1.22.5 stable channel

Getx Version:
get: ^3.22.2

Describe on which device you found the bug:
pixel api 28 5 inch - Android.

Minimal reproduce code
same as above

bug

All 16 comments

change:

Prime()
  {
    Get.put(PrimeController());
  }
  @override
  Widget build(BuildContext context) {

to:

  @override
  Widget build(BuildContext context) {
  Get.put(PrimeController());

The class constructor is called before the route, so it is attached to the previous route.

@jasonlaw so, instead of adding the put inside the constructor i should add it to the build?
if yes, i already did that and i got the same result..

@xEyad, after making the modification that @jasonlaw indicated, how was your Prime class?
Put a print on the onClose method to make sure it doesn't go through it.

same here!
i go to a page like product counter page, firstly i enter to this page counter is 0 and GetXController print some thing that is on onInit() function, i set counter to 5 and then i press back button and close the page when i go to page for second time the counter value is 5 and onInit() function is not called again! also i write onClose() function too but it is not working.
help me please!
@xEyad @jonataslaw @jasonlaw @lsm

Apparently the initial route is being appended to '/', however you are not using named routes. I'm doing a hotfix now for this

same here!
i go to a page like product counter page, firstly i enter to this page counter is 0 and GetXController print some thing that is on onInit() function, i set counter to 5 and then i press back button and close the page when i go to page for second time the counter value is 5 and onInit() function is not called again! also i write onClose() function too but it is not working.
help me please!
@xEyad @jonataslaw @jasonlaw @lsm

Had similar problem, for now you can use binding, everything works fine with that.

same here!
i go to a page like product counter page, firstly i enter to this page counter is 0 and GetXController print some thing that is on onInit() function, i set counter to 5 and then i press back button and close the page when i go to page for second time the counter value is 5 and onInit() function is not called again! also i write onClose() function too but it is not working.
help me please!
@xEyad @jonataslaw @jasonlaw @lsm

Had similar problem, for now you can use binding, everything works fine with that.

binding sounds like a lot of work that's why i didn't use it in the first place, and this also means either A. i will do this only for the current issue i have in the given screen only making an inconsistency with my whole codebase or B. change my whole codebase to use bindings instead of the current method.

but regardless of my preference i may have to resort to B because i won't ever know when i will encounter this issue again and it may go under the radar.
i really do hope that jonataslaw fix this issue fast. so far GETX is the best state management library i have used and i really like it.
anyways, if this problem won't be solved soon, may you tell me so that i adopt the alternative solution early instead of waiting for a fix.

_sorry for the long rant._

@xEyad take a look at BindingsBuilder, very easy to use

Get.to(MyPage(), binding: BindingsBuilder(() {
                        Get.put<GController>(GController());
                      }),
                    );

is the bug fixed ?

I fix this bug with defining controller after build context, thanks all

On Sun, Jan 3, 2021, 3:18 PM F-BONAPARTA notifications@github.com wrote:

is the bug fixed ?

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jonataslaw/getx/issues/961#issuecomment-753605241,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AKXWV4A2GHQT574LFULW4C3SYBKQHANCNFSM4VNULOVA
.

is the bug fixed ?

nope

I fix this bug with defining controller after build context, thanks all
interesting, that didn't fix it when i used this solution.

is the bug fixed ?

nope

I fix this bug with defining controller after build context, thanks all
interesting, that didn't fix it when i used this solution.

could you please share your code?

I have the exact same issue with Timers.. even if GetX logs says the screen is fully deleted in memory, still the timer is still alive and kicking

same here!
i go to a page like product counter page, firstly i enter to this page counter is 0 and GetXController print some thing that is on onInit() function, i set counter to 5 and then i press back button and close the page when i go to page for second time the counter value is 5 and onInit() function is not called again! also i write onClose() function too but it is not working.
help me please!
@xEyad @jonataslaw @jasonlaw @lsm

@jonataslaw @eduardoflorence

With get: ^3.26.0 I experience a similar behavior but when I use id in Get.to()

FlatButton(
                          onPressed: () {
                            Get.to(() => DummyView(), binding: BindingsBuilder(() {
                              Get.put<DummyController>(DummyController());
                            }));
                          },
                          child: const Text(
                            'Dummy view',
                          ),
                        ),
class DummyController extends GetxController {
  final RxInt counter = 0.obs;

  void increment() {
    counter.value++;
  }

  @override
  void onInit() {
    logger.w('Dummy controller launched, counter value : $counter');
    super.onInit();
  }
}
class DummyView extends GetView<DummyController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              Obx(
                () => Text('Counter value : ${controller.counter.value.toString()}'),
              ),
              RaisedButton(
                onPressed: () {
                  controller.increment();
                },
                child: const Text('Increment counter'),
              )
            ],
          ),
        ),
      ),
    );
  }
}

The controller is not deleted from memory if I use id

Get.to(() => DummyView(), id: 1, binding: BindingsBuilder(() {
                              Get.put<DummyController>(DummyController());
                            }));

Same problem with named routes

@zzterrozz, Why are you using id in Get.to? We only use id when we are working with Nested Navigation.
https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md#nested-navigation

We have the same use case as @zzterrozz. We use nested navigation in our app, and it seems like no Controllers are ever deleted.

Was this page helpful?
0 / 5 - 0 ratings