jonataslaw / getx

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

Questions for Converting From Provider #525

Closed yasinarik closed 4 years ago

yasinarik commented 4 years ago

Ok.

roipeker commented 4 years ago

@yasinarik If you have any questions on how to use the package, please use the proper channels: Look for GetX Community channels in the readme, Telegram and Discord are very responsive, we'll be happy to help you out. @jonataslaw / @Nipodemos would you mind closing the issue?

jonataslaw commented 4 years ago

When using GetBuilder, what if we need multiple controller classes? In Provider package we have the MultiProvider package. It’s useful to wrap other widgets. GetX does need a wrap too.

- Bindings

How can I depend on multiple GetX controllers inside the GetBuilder? (Maybe wrapping them over and over just works but is there a better syntax for readability? Get.find\<OtherController>()

Sorry, but the other questions are supportive. This channel is exclusive for opening issues, or requesting resources. The platform channels are suitable for you to get support from the community.

Since this is not a description of bugs or a feature request, I am closing this.

Nipodemos commented 4 years ago

How can I depend on multiple GetX controllers inside the GetBuilder? (Maybe wrapping them over and over just works but is there a better syntax for readability? Get.find()

it does not work jonatas let's say i have a text that half from one controller and half of another one

if i don't call the update method of the controller that was in the GetBuilder, it won't rerender: here is an example: hdVeMnjVew here is reproducible code:

class FirstController extends GetxController {
  String firstWord = "Hey";

  void updateWord() {
    this.firstWord = "Hello";
    print('updating first part to "Hello"');
    update();
  }
}

class SecondController extends GetxController {
  String secondWord = "World";

  updateWord() {
    this.secondWord = "to you!";
    print("updating second part to 'to you!'");
    update();
  }
}

class GetBuilderViewPage extends StatelessWidget {
  final secondController = Get.put<SecondController>(SecondController());
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetBuilderViewPage')),
      body: Container(
        child: Column(
          children: [
            GetBuilder<FirstController>(
              init: FirstController(),
              builder: (controller) {
                return Text(
                  '${controller.firstWord} ${secondController.secondWord}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            RaisedButton(
              child: Text('update to "Hello to you!"'),
              onPressed: () {
                // if i don't call the update method of the first controller, it will not rerender
                // Get.find<FirstController>().updateWord();
                Get.find<SecondController>().updateWord();
              },
            )
          ],
        ),
      ),
    );
  }
}
jonataslaw commented 4 years ago

As I recall (I haven't used Provider for over a year), multiproviders are just for injecting multiple ChangeNotifier classes into the tree. Bindings are a more readable and decoupled way of doing this.

When it comes to nesting GetBuilder, I believe that this is impossible in any type of state management other than Getx (reactive), and perhaps Mobx, but Provider, Bloc, nor Simple State Manager of Get will be able to reproduce this example successfully, simply because they are widgets connected to controllers/blocs/changeNotifiers.

There is Value + SimpleBuilder that I didn't even document that is the most effective way to do this, however, it is not based on Streams, so it loses a little bit of power, however, it has the build time 6x faster than Rx , Bloc, Provider, or even a StreamController + StreamBuilder.

I'm testing this to see if I can create a notification pool, so that I can add Streams, using the simplicity of the hashset notifier.

jonataslaw commented 4 years ago

Try:


class FirstController extends GetxController {
  final firstWord = Value<String>("Hey");

  void updateWord() {
    this.firstWord.value = "Hello";
    print('updating first part to "Hello"');
  }
}

class SecondController extends GetxController {
  final secondWord = Value<String>("World");

  updateWord() {
    this.secondWord.value = "to you!";
    print("updating second part to 'to you!'");
  }
}

class GetBuilderViewPage extends StatelessWidget {
  final controller = Get.put<FirstController>(FirstController());
  final secondController = Get.put<SecondController>(SecondController());
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetBuilderViewPage')),
      body: Container(
        child: Column(
          children: [
            SimpleBuilder(
              builder: (_) {
                return Text(
                  '${controller.firstWord.value} ${secondController.secondWord.value}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            RaisedButton(
              child: Text('update to "Hello to you!"'),
              onPressed: () {
                // if i don't call the update method of the first controller, it will not rerender
                Get.find<FirstController>().updateWord();
                Get.find<SecondController>().updateWord();
              },
            )
          ],
        ),
      ),
    );
  }
}
jonataslaw commented 4 years ago

I need an opinion on the Value. It has about 100 lines of code, it doesn't work with Streams, it's fast, but it's not as powerful as Rx. I don't know if I present it as an intermediate alternative (it will be confusing 3 State Managers in 1 package). If I try to migrate it with Rx (I don't know if it would be a good option, Workers and bindStream are basically Rx's biggest competitive advantage over other State managers). I don't know what I do.

Nipodemos commented 4 years ago
 final firstWord = Value<String>("Hey");

man you always have something under your sleeves huh? 🤯

jonataslaw commented 4 years ago

I always want to have the best performance option, the best build time option, and the lowest memory consumption, and sometimes I insert these experimental things to test benchmarks. Value is undoubtedly the lightest and simplest way to manage states, if we used dart extensions, to create something like:

final name = "jonny" .reactive;

It would be so much easier than anything else.

But I don't know how users would react to the addition of yet another intermediate State manager.

Nipodemos commented 4 years ago

that's a hard question to answer to be honest it really would not be so nice to have another intermediate

if it was possible for a widget that listen to every update() that is called in controllers without change the variable declaration ( like a SimpleBuilder but without have to type text.value and Value<string>('') it would be perfect but i can imagine that is not that simple

jonataslaw commented 4 years ago

Unfortunately this is not possible with dart, because it does not let you extend String, int, num, and there is no way to override the setter operator "=". So that will unfortunately not happen, maybe never.

Nipodemos commented 4 years ago

well, getbuilder is not made to help in every situation anyway, it is made to simple things

maybe then we should add to docs the limitations of getBuilder instead of trying to make it get more and more closer to getx