jonataslaw / getx

Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
MIT License
10.08k stars 1.58k forks source link

flutter: example: GetX => HeavyWidget => variableObservable #1942

Open tazik561 opened 2 years ago

tazik561 commented 2 years ago

I am trying to use GETX on my project. After installing getx lib and changing materialapp to GetMaterialApp :

GetMaterialApp(
        initialBinding: AppBinding(),
        title: 'Test App',
        themeMode: ThemeMode.light,
        theme: customLightTheme,
        debugShowCheckedModeBanner: false,

I made a binding class for one of my pages:

class MateMapBinding implements Bindings {
  @override
  void dependencies() {
    Get.put<MateMapController>(MateMapController());
  }
}

I have a page called MateMapScreen and by Get.to I move to this page:

Get.to(() => MateMapScreen(), binding: MateMapBinding());

In MateMapScreen page I am trying to use GetX like this:

class MateMapScreen extends GetView<MateMapController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(19),
        child: Column(
          children: [
            SizedBox(
              height: 12,
            ),
            Container(
              height: 60,
              child: Row(
                children: [
                  GetX<MateMapController>(
                    initState: (_) => Get.find<MateMapController>().start(),
                    init: controller,
                    builder: (_) {
                      return Expanded(
                        child: Container(
                          color: Colors.red,
                        ),
                      );
                    },
                  ),
                ],
              ),
            ),

The problem is here! when MateMapScreen is started I got error:

[GETX] GOING TO ROUTE /() => MateMapScreen
[GETX] Instance "MateMapController" has been created
[GETX] Instance "MateMapController" has been initialized
I/flutter ( 4415): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 4415): The following message was thrown building GetX<MateMapController>(dirty, state:
I/flutter ( 4415): GetXState<MateMapController>#81ec8):
I/flutter ( 4415):       [Get] the improper use of a GetX has been detected.
I/flutter ( 4415):       You should only use GetX or Obx for the specific widget that will be updated.
I/flutter ( 4415):       If you are seeing this error, you probably did not insert any observable variables into
I/flutter ( 4415): GetX/Obx
I/flutter ( 4415):       or insert them outside the scope that GetX considers suitable for an update
I/flutter ( 4415):       (example: GetX => HeavyWidget => variableObservable).
I/flutter ( 4415):       If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX.
I/flutter ( 4415):
I/flutter ( 4415): The relevant error-causing widget was:
I/flutter ( 4415):   GetX<MateMapController>
eMapScreen` page is started I got this error:

but when I press ctrl + s (hot reload), the error is gone and red color container is appeared . What is my mistake?

maares commented 2 years ago

@tazik561 when you are using GetView, this will try to create the controller automatically if you added the binding (see last part)


class MateMapScreen extends GetView<MateMapController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(19),
        child: Column(
          children: [
            SizedBox(
              height: 12,
            ),
            Container(
              height: 60,
              child: Row(
                children: [ Text(controller.count.value);
                  ]
                    },
                  ),
                ],
              ),
            ),

I can see your are trying to execute

Get.find<MateMapController>().start(),

Do not know your use case, but try to call it on init


class MateMapController extends GetxController{

  final int count= 0.obs;

  @override
  void onInit() {
    start();
    super.onInit();
  }

void start(){
count.value = 1;
}

....

Something I recommend is to generate the app_routes class. As you can specify the bindings, when a Widget is using a controller. That will ensure all necessary ctrls are up before hand, executed, run and close automatically.

GetPage(
        name: Routes.NAME,
        page: () => TargetPage(),
        binding: TargetBinding(),
        fullscreenDialog: true)

Then simple call:

Get.toNamed(Routes.NAME);

jonataslaw commented 2 years ago

GetX<MateMapController>(

GetX need a reactive variable, swap it to GetBuilder it you will not to use reactive variables.

init: controller,

remove this

initState: (_) => Get.find<MateMapController>().start(),

You dont need this, call start function on onInit of MateMapController.