Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why Controller can't close #384

Closed
KeepFish opened this issue Jul 15, 2020 · 9 comments
Closed

Why Controller can't close #384

KeepFish opened this issue Jul 15, 2020 · 9 comments

Comments

@KeepFish
Copy link

This is page

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

class TruckListPage extends StatelessWidget {

  final TruckListController c = Get.put(TruckListController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App bar'),
      ),
      body: Text('21321312'),
    );
  }
}

This is controller

import 'package:get/get.dart';

class TruckListController extends GetxController {

  @override
  void onClose() {
    print('TruckListController onClose');
    super.onClose();
  }
}

When push in TruckListPage and pop. Print in console like
image
Why onClose method is not called.

@KeepFish
Copy link
Author

class TruckListPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final c = Get.put(TruckListController());

    return Scaffold(
      appBar: AppBar(
        title: Text('App bar'),
      ),
      body: Text('21321312'),
    );
  }
}

When I put the Get.put in build, it's fine..... Why?
image

@jonataslaw
Copy link
Owner

Please follow the steps for opening the issue, explaining data such as Get version and reproduction of the problem.
Both inside and outside the build the controller is being excluded in my test, so you must provide a case of reproducing the problem.

@KeepFish
Copy link
Author

Get version: 3.3.0
IDE: Android Studio 3.2.1 in macOS 10.14.5
Dart Version: 2.8.4

Reproduction:
Run 'flutter create myapp'
Then add some file like
image
in main.dart

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

void main() => runApp(GetMaterialApp(home: MyHomePage()));

class MyHomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('app'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Get.to(SecondPage());
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

in second_page.dart

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

class SecondPage extends StatelessWidget {
  final c = Get.put(SecondController());

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('SecondPage'),
      ),
      body: Container(
        color: Colors.red,
        height: 100,
        width: 100,
      ),
    );
  }
}

in second_controller

import 'package:get/get.dart';

class SecondController extends GetxController {

  @override
  void onInit() {
    print('SecondController init');
    super.onInit();
  }

  @override
  void onClose() {
    print('SecondController onClose');
    super.onClose();
  }
}
  • Put the code final c = Get.put(SecondController()); out of build method. Run app in simulator, click button push in SecondPage then pop back. The print in console is
flutter: [GET] GetMaterialController has been initialized
flutter: [GOING TO ROUTE] /
flutter: SecondController init
flutter: [GET] SecondController has been initialized
flutter: [GOING TO ROUTE] /SecondPage
flutter: [BACK ROUTE] /SecondPage
  • When put code in build method
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final c = Get.put(SecondController());
    return Scaffold(
      appBar: AppBar(
        title: Text('SecondPage'),
      ),
      body: Container(
        color: Colors.red,
        height: 100,
        width: 100,
      ),
    );
  }
}

Restart the simulator and do it again. The print in console is

flutter: [GET] GetMaterialController has been initialized
flutter: [GOING TO ROUTE] /
flutter: [GOING TO ROUTE] /SecondPage
flutter: SecondController init
flutter: [GET] SecondController has been initialized
flutter: [BACK ROUTE] /SecondPage
flutter: SecondController onClose
flutter: [GET] onClose of SecondController called
flutter: [GET] SecondController deleted from memory

So my question is:
Why onClose method does't called in first case.
What's the difference between put final c = Get.put(SecondController()) in build method and out of build method.
Without Binding only use controller. Is correct in my case? If not, what's the correct way.

@KeepFish
Copy link
Author

Please follow the steps for opening the issue, explaining data such as Get version and reproduction of the problem.
Both inside and outside the build the controller is being excluded in my test, so you must provide a case of reproducing the problem.

Sorry, forgot to reply. You can see my last comment.

@jasonlaw
Copy link
Contributor

I noticed the same behavior as well.

@KeepFish
Copy link
Author

I noticed the same behavior as well.

I had figured out.
Get.put(SecondController()) will put a controller in a controllerMap and route-controller-Map. In controllerMap the key is SecondController, another is currentRoute.
In case 1, Get.put((SecondController()) will be executed before the page push done, the currentRoute is still HomePage, so the map is like {HomePage: SecondController}, so when pop back it will not deleted from memory.
In case 2, Get.put((SecondController()) in build method, so the currentRoute is SecondPage, after pop back, Get will remove SecondPage and SecondController from map.

Fortunately if you execute Get.put(SecondController()) many times it will return the same Controller you first put. So in technically it's ok to execute Get.put() in build method.
I don't know is right or not. Hope to get an official answer or another solution.

@jasonlaw
Copy link
Contributor

@jonataslaw any comments? Thanks.

@jonataslaw
Copy link
Owner

When you do:

Get.to (Page())
Specifically in:
Page()

You are closing and creating your instance.
Get.put(), unlike Get.lazyPut(), creates the instance the moment it is called, and believe me, the implicit dart constructor already initialized it the moment you closed the second parenthesis.

Therefore, the instance will be created on the first route, and linked to it.

This is the big problem with unnamed routes.
If the current syntax were:
Get.to(() => Page());
I could postpone the creation of the instance until later, but that would not please most users.

So for now you can:
1-Use named routes.
2-Use in the build, as you are using
3-Use Get.lazyPut instead of Get.put ();
4-Use the GetX/GetBuilder widget to start your controllers.
5-Use Bindings.

Of all the combinations that exist, the only one that doesn't work is:
Get.put created as final + unnamed routes + no Bindings.

@KeepFish
Copy link
Author

Much appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants