jonataslaw / getx

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

About "Complete example of the Flutter counter app in just 11 lines with Get" #184

Closed Nipodemos closed 4 years ago

Nipodemos commented 4 years ago

Is your feature request related to a problem? Please describe. I my opinion, this example do not show how good GetX is as a state management. When i saw this code, i wondered: why don't simply make a normal variable and update it normally? I know the counter app is too simple to elaborate, but i think it would be better if you made a controller class and a view class, so it would be more realistic.

Describe the solution you'd like I would suggest something like this:


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

class CounterController extends RxController {
  final count = 0.obs;
}

class Home extends StatelessWidget {
  final CounterController controller = Get.find();
  @override
  Widget build(context) {
    return Scaffold(
    appBar: AppBar(
      title: Text("Get change you life"),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () => controller.count.value++,
    ),
    body: Center(
      child: Obx(() => Text(controller.count.string)),
    ),
  );
}

Note: i don't know if the controller class needs to extends RxController, i saw one place in README that extended, and other place that did not (and this example you put the .obs inside the view, which made me even more confused)

Anyway, this is just a suggestion on style of your documentation, i am revising it and want to make some small improvements, step by step

jonataslaw commented 4 years ago

I really agree. The question of putting everything in, is similar to a setState, and I did it just to make an impact with the phrase "counter in 11 lines". But since I got what I wanted, I think it's time to professionalize things. I am working on "core concepts", I will divide the documentation into 3 (Route management, State management, dependency management), because I think it is currently a bit messy.

I'm also having fun with benchmarks:

bloclib mobx provider Screen Capture_20200604161652

Nipodemos commented 4 years ago

i actually really like the ideia of splitting in those three big sections! it would be very well organized. Have you thought about using some site to post your documentation like docusaurus? i think it could be a nice ideia, specially because they separate docs by version, and since you are making constants improvements, this could be useful. And have support for multiple languages ❀️

i don't know how to read those devtools informations, but what i understand is get is lighter than provider and mobx in terms of RAM? don't know if it is right

jonataslaw commented 4 years ago

i actually really like the ideia of splitting in those three big sections! it would be very well organized. Have you thought about using some site to post your documentation like docusaurus? i think it could be a nice ideia, specially because they separate docs by version, and since you are making constants improvements, this could be useful. And have support for multiple languages

i don't know how to read those devtools informations, but what i understand is get is lighter than provider and mobx in terms of RAM? don't know if it is right

I liked the docusaurus idea. Yes, it is literally the state manager that consumes less RAM and CPU, and now this can be proven hahaha. I don't know if it would be ethical to raise a benchmark here in the repository with all other state managers, but I will think about doing that too.

stefandevo commented 4 years ago

At least it would prove your point you made from the beginning, although other maintainers will not be happy to see you were right 😎. Organised docs would be a great step; I daily read all (closed)questions here and every day I learn something new :-)

rrousselGit commented 4 years ago

I don't know if it would be ethical to raise a benchmark here in the repository with all other state managers, but I will think about doing that too.

As long as the source of the benchmark is open source and the documentation to run it ourselves is here, it should be fine.

stefandevo commented 4 years ago

I don't know if it would be ethical to raise a benchmark here in the repository with all other state managers, but I will think about doing that too.

As long as the source of the benchmark is open source and the documentation to run it ourselves is here, it should be fine.

That would be great ...

On a site note I don't really understand why you @rrousselGit are so closely monitoring this as on other channels (like reddit) you actually said this library was "so bad" (with other words). There are thousands of dart/flutter libraries and they all exists because a certain problem their creators had is fixed the way they want. Nobody forces you to use a library, so it's up to the user to use it or not. I like this one now, but I am not bashing Provider for it :-)

rrousselGit commented 4 years ago

Nobody is bashing the package. Criticism made are about its readme, and that's not just me but nearly everyone I spoke to (and I spoke to a bunch of people).

The readme is written in an overly exaggerated way, with many multiple false informations or unproven points. This is kind of the fake news of readmes.

An example is available in this exact thread: " I did it just to make an impact with the phrase "counter in 11 lines". Other packages could do the same, but they are ethical and don't.

stefandevo commented 4 years ago

So it's about the ethics then. So maybe @jonataslaw can remove all references to Provider (and other packages) out of the Readme to become more ethical. That would solve it. And for comparison and reason for the library mention "In my opinion". That leaves us all with our own opinions.

In the end it all comes to how a dev or dev teams feels about a way of working. I have 25+ years o dev experiences in small and large (>100) teams; I used different techs in my life. I often saw over engineered applications / apps that were made "following the best standards/architectures" and finally where not delivered on time and on budget. When I started using Flutter last year I was really upset with all the different opinions about state management, libraries, etc. At Flutter Europe (you were there too), some talks began with "About State Management..." followed by a room of people starting laughing... That was exact what I felt all the time... Why make it all so difficult and opinionated... Choose what is best for you and your team. This package is evolved that it allows testing (abstract classes in the DI), and works really fast with very little boilerplate code. So I like it. I use it. Case closed.

rrousselGit commented 4 years ago

I haven't seen anyone forcing anything. The problem is more the opposite: People are laughing about state management because it is not opinionated and as such there are too many options.

But that's ok. And like I said when people asked me about state_rebuilder or flutter_module or whatever other state-management approach: If it helps, it's fine.

I myself am a defender of the idea of making new packages if people think they can fix some problems.

So maybe @jonataslaw can remove all references to Provider (and other packages) out of the Readme to become more ethical. That would solve it.

That would help, but that's not all. The problem is in how the readme is written.

Multiple misinformations had to be corrected already, and the tone of the readme is pretentious. I believe that these will be fixed over time, but it shouldn't be an issue to begin with.

I've seen multiple people on social medias that have been misled by statements made in the readme. That's not good

I believe that a package should be attractive because of its benefits, not because the readme is written in a fancy way.

jonataslaw commented 4 years ago

I haven't seen anyone forcing anything. The problem is more the opposite: People are laughing about state management because it is not opinionated and as such there are too many options.

But that's ok. And like I said when people asked me about state_rebuilder or flutter_module or whatever other state-management approach: If it helps, it's fine.

I myself am a defender of the idea of making new packages if people think they can fix some problems.

So maybe @jonataslaw can remove all references to Provider (and other packages) out of the Readme to become more ethical. That would solve it.

That would help, but that's not all. The problem is in how the readme is written.

Multiple misinformations had to be corrected already, and the tone of the readme is pretentious. I believe that these will be fixed over time, but it shouldn't be an issue to begin with.

I've seen multiple people on social medias that have been misled by statements made in the readme. That's not good

I believe that a package should be attractive because of its benefits, not because the readme is written in a fancy way.

Well, about making an impact, I meant literally running the 11-line counter example, which is impossible with any other state manager. But it is an approach not recommended by the library itself as it does not separate View's business logic. My intention was only to cause the impact of using the Get syntax, which is less in any situation. Flutter Inheriteds that need MediaQuery.of (context) .size.height can be summed up in Get.height, and this syntax is in the whole package, in every function. And I agree about ethics, so I haven't updated the benchmarks so far. But Get really manages to use less memory than the other state managers, and as much as we have discussed in numerous forums about StatelessWidget and StatefulWidget, it is obvious, of course, of course, that StatefulWidget is a larger class (in fact, two larger classes , because StatefulWidget needs the State class, which is also a larger class), and that you don't realize when you have 1, two widgets, but 400 of them. In this regard, I think it is a matter of discussing it for nothing, it doesn't take much, just logic to reach that conclusion. Well, I don't need to lie about the package, here in my country a user made a video about MobX and Get, and he took a lot of hate from users for exposing false information like "Get has no individual flow", when GetX besides reconstruct only the variable that was changed, it has a flow control that only updates the Widget if the state really changes (as well as the Provider Selector, and congratulations on the idea, despite using streams and doing it in a completely different way, I confess I thought it was cool in the provider, and implemented it in GetX). We are close to launching our CLI and taking this package to another level. I have received emails from companies all over the world looking for advice on how to use Get, and if you are going through the issues you will see that a giant US company is using Get, including the CLI was their idea at our last meeting. And in addition to addressing the technical issues of the package, I've been wasting time on discussions like this that shouldn't happen. About the readme, you opened an issue explaining how the provider works, and I changed the readme, not because I had a lie (because it just said that provider used changeNotifier, which is true), but to make it clear how things work with provider. However, you have also been spreading false information, such as "the lib will be deprecated with the arrival of Navigator 2.0", and I think that should stop too. I honestly think your problem is personal to me (since the first discussions about the unexpected reconstruction of MaterialApp). You have always been conservative about how things work, and I always take a chance on something new, as long as it guarantees me 1 CPU cycle less, our thoughts are always shocked by this, and I don't mean that there is someone right or wrong, but simply that we have completely different approaches to working. Is it possible for us to solve this at once and get on with life? If you want I even include the provider as an alternative in the CLI of Get, I never imagined that I would be discussing in 2020 about state managers, because when you launched Provider, I was one of the defenders of your package worldwide saying that it was better than scopped_model and the bloc_pattern package (bloc_pattern had a consumer like Provider, not like flutter_bloc). At no point in the readme do I force people to use Get under false pretense, on the contrary, I try to explain all state managers so that they choose when to use them together, or separately with Get. If you want we can talk about it in a private chat and get it over with once and for all, because talking badly about the other's package won't add anything to the community, on the contrary, it will make people more and more confused. I don't mind talking about constructive criticism, you and stefandevo were responsible for one of the major lib updates that is still going on. Tests, github actions, and a ton of other things that were missing, gained a little more of my attention thanks to you, as I was only concerned with updates and new features. I really have no problem with criticism, because they make me deliver a better and better product. But my problem is with this "war" between packages, this is unnecessary. You were the first person to join the gitter of Get, and you are always in controversial issues like this, and I think you’re watching the project closely, but all this time wasted on this issue could be used to create something really useful to the community, that would help both experienced and novice devs to work better with Flutter.

Get CLI will integrate templates, and this will certainly be a milestone in the history of Flutter, the dev with literally a line will integrate and configure packages, and I will allow the package creators themselves to make their "suggestion" of use "of your package (some social login creator for example, for writing your own template to use get-cli with his package). My goal is not to gain evidence for launching a package, but to really change the lives of the people who are developing it. I really don't care about this whole fight, I just want to develop my apps in a satisfactory way, and that other devs have the same experience, and I think this fight is all unnecessary, and I sincerely want that if this is something personal, that we resolve it in a timely manner. once.

rrousselGit commented 4 years ago

Well, about making an impact, I meant literally running the 11-line counter example, which is impossible with any other state manager.

That's not true. Mobx, flutter_hooks, .... Even Flutter without any package can achieve the same number of lines (assuming you rename ValueListenableBuilder/AnimatedBuilder to Obx for the 80 char limit).

MediaQuery.of (context) .size.height can be summed up in Get.height

Get.height is dangerous. By removing the context, it doesn't work anymore with responsive applications.

MediaQuery.of(context).size.height rebuilds widgets that uses the size when that size change (web = resizing window, mobile = orientation). But Get.width doesn't

However, you have also been spreading false information, such as "the lib will be deprecated with the arrival of Navigator 2.0"

I'm not saying "the lib will be deprecated", but "the navigation part of Get", more specifically https://github.com/jonataslaw/get#navigate-with-named-routes

How do you plan on making the migration?

Navigator 2.0 removes Navigator.pushNamed & co. Get is syntax sugar on the top of these

These functions cannot be reimplemented with Navigator 2.0 without loosing the benefits of Navigator 2.0 (automatic state restoration).

I honestly think your problem is personal to me (since the first discussions about the unexpected reconstruction of MaterialApp). You have always been conservative about how things work

No you are misunderstanding what I'm saying.

I have no problem with the code. I am fine with the existence of Get. I'm in fact interested in it, and follow it to see what it tries to solve and what are the issues encountered by users.

My issue with it is exclusively the tone of the readme, and multiple people have agreed with me. Reddit itself included some people making this argument:

The Readme is written in a way that hurts the community becauses it confuses people.

Peeople asked about the MaterialApp freeze, they asked about StatefulWidget consuming a lot of ram, or about ChangeNotifier being underperformant. They asked it because the readme mentioned problems without explaining clearly what they are and while making it seem like these problems are horrible.

You fixed some of these issues, so it's great. But I still think some improvements could be made (for example add the benchmarks for your RAM statements).

Anyhow, I agree that my tone wasn't proper too and I apologise. Your work is appreciated. Just make sure to not confuse people and be pretentious.

rrousselGit commented 4 years ago

By the way, could you share the link to the cli discussion? I'm interested.

1N50MN14 commented 4 years ago

I just stumbled upon this issue, only been using Get less than a day, and my background is similar to that of @stefandevo's, mostly back-end, high obsession with minimal reusable modular code.

I rarely, if ever, comment on anything that is not directly related to code but I feel I need to share my personal experience, also about the README itself. I'm also not a Flutter guru, just your average joe with some years on my belt.

1. README Yes, it's not written in a perfectly "professional" manner, yes many sentences can be formulated better, yes at times the "tone" might sound like "this is great you should try it you get this and that X benefits" and if you've been doing this for so long you'd normally close the browser tab and go back to your professionally documented X module, or whatever, that simply works instead of risking it.

But that wasn't what I did, I instead decided to give it a go, and the reason for that is simple: It's written from the heart by an unlikely guy who's English is not even is his first language. For all that I care, he could've written an essay about flowers, ice-cream and unicorn milk and I would've still opted to give it a try.

2. What was I looking for

  1. Get rid of all of the noise which in my opinion should've been baked under the hood into Flutter, including StatefulWidgets, "builders" or what not so I could keep my code minimal.

  2. Bugs, syntax sugar are fine as long as they are predictable - the code is readable there's no hidden magic in there, any pain points are clearly visible or can be worked around. Happy to trade those for performance and improved productivity.

3.Does it deliver? I have been using MobX for over a year (both backend and Flutter), and Provider for half a year. I love them both, the maintainers of MobX Dart are wonderful, responsive to issues and concise. Provider just works not a single negative word I can say about it. If anything, I'm grateful they exist.

But I did end up switching over to Get. @jonataslaw must be doing something right, and maybe, just maybe it's the imperfect README.

Imho, this issue should be closed and everyone should move on, we live at moment of time in history when we should be thankful for whatever contribution each person is doing to help others, be Get, Provider, packageX, Y or Z.

Peace.

jonataslaw commented 4 years ago

Well, about making an impact, I meant literally running the 11-line counter example, which is impossible with any other state manager.

That's not true. Mobx, flutter_hooks, .... Even Flutter without any package can achieve the same number of lines (assuming you rename ValueListenableBuilder/AnimatedBuilder to Obx for the 80 char limit).

Mobx this is not impossible, as only the action would already exceed the limit of lines. Using ValueListenable and AnimatedBuilder, it could be around 13 lines, which is great. I have never used flutter_hooks, I cannot comment on, but from the solutions you mentioned that I know, they can come close, not reach 11 lines. But I don't think it makes sense to argue about it.

MediaQuery.of (context) .size.height can be summed up in Get.height

Get.height is dangerous. By removing the context, it doesn't work anymore with responsive applications.

MediaQuery.of(context).size.height rebuilds widgets that uses the size when that size change (web = resizing window, mobile = orientation). But Get.width doesn't

This is not dangerous, just immutable, so version 3.0 will have extensions in the context and the documentation will specify the usage situation for each one. But this is a great observation, I will even mention it in the documentation.

However, you have also been spreading false information, such as "the lib will be deprecated with the arrival of Navigator 2.0"

I'm not saying "the lib will be deprecated", but "the navigation part of Get", more specifically https://github.com/jonataslaw/get#navigate-with-named-routes

How do you plan on making the migration?

Navigator 2.0 removes Navigator.pushNamed & co. Get is syntax sugar on the top of these

These functions cannot be reimplemented with Navigator 2.0 without loosing the benefits of Navigator 2.0 (automatic state restoration).

I have been working on this for a long time since the idea of ​​"Navigator 2.0" was born, but I anticipate that Get will have its own implementation of this using Navigator 1.0 or Navigator 2.0. Navigator 2.0 is very new, I have a lot of respect for the work the chuntai is doing, even though there are some things that I don't agree with, but that don't make much difference to me. Dynamic routes and many other things will continue to exist. I am looking at Navigator 2.0 to be sure if I will use Get with Navigator 1.0 that will continue to work, or if it will be a kind of Middleware to handle routes, but in both cases, nothing will be deprecated, and in both alternatives, Get will continue with all possible resources existing in navigation. The restoration of state was something that I targeted a long time ago when I created GetObserver, and there are many paths to follow.

No you are misunderstanding what I'm saying.

I have no problem with the code. I am fine with the existence of Get. I'm in fact interested in it, and follow it to see what it tries to solve and what are the issues encountered by users.

My issue with it is exclusively the tone of the readme, and multiple people have agreed with me. Reddit itself included some people making this argument:

The Readme is written in a way that hurts the community becauses it confuses people.

Peeople asked about the MaterialApp freeze, they asked about StatefulWidget consuming a lot of ram, or about ChangeNotifier being underperformant. They asked it because the readme mentioned problems without explaining clearly what they are and while making it seem like these problems are horrible.

Well, I believe you remember our first discussion that I talked about freezing apps with many routes due to the unexpected reconstruction of MaterialApp, do you remember? So, this is a problem that has existed since the creation of Flutter, and that Godebauer fixed definitely in version 1.17.0 This was a problem, and it was fixed, so much so that on the release date of the stable version with Fix, I removed this reference from the Readme.

StatefulWidget consumes more RAM than StatelessWidget, Flutter documentation, logic, common sense says that. This does not mean that it is too much RAM. But if you exchange 300 Stateless widgets for Stateful in your project, you will see that consumption in this case will increase. If you want, I can do an example repo, no problem. The problem is not that StatefulWidget is bad, the problem is that people don't know how to use it, and they keep creating StatefulWidgets for immutable widgets, and with Get unless you need TicketProviderMixin or AutomaticKeepAlive, you can forget about its existence. I don't know how that sounds to you, but I definitely didn't write with the intention of saying that StatefulWidgets should be abandoned, but with the intention of saying that it is the exception, not the rule.

ChangeNotifier is bad for performance. The way you do with provider is not bad, but apart from the approach you use, ChangeNotifier is bad. And that is in the documentation. There are hundreds of state managers in the pub who use ChangeNotifier. Your approach is good, but it's not the rule, it's the exception.

You fixed some of these issues, so it's great. But I still think some improvements could be made (for example add the benchmarks for your RAM statements).

Well, I would have done that before, but I don't know if this is ethical, because perhaps it would detract from the work of the last positions of StateManager. The problem is not Provider, it was just behind Get among 12 state managers by an even small margin. But the problem is that others are at the bottom, and are widely used. There are a lot of people who will do sensational material treating these managers like trash, and I don't want that, as I said, I want everyone to grow together and evolve, this is community. I do not want that for Get to have evidence, another manager is overlooked. It is one thing to say technical and general knowledge, such as the absence of a "selector" in MobX, or the need to use context in Provider, it is another thing to do a benchmark and say that a package consumes 16mb more on a single simple screen. . I don't really know if I should do this.

Anyhow, I agree that my tone wasn't proper too and I apologise. Your work is appreciated. Just make sure to not confuse people and be pretentious.

I'm not pretentious, and I didn't write anything like that in the readme.

Maybe something could have interpreted this (I don't know, English is not my first language, I just refused an invitation to work at a multinational outside my country because of that), but definitely, my goal is just to help people decide whether they use Get pure, or it in conjunction with another state manager or dependency injector.

jonataslaw commented 4 years ago

I just stumbled upon this issue, only been using Get less than a day, and my background is similar to that of @stefandevo's, mostly back-end, high obsession with minimal reusable modular code.

I rarely, if ever, comment on anything that is not directly related to code but I feel I need to share my personal experience, also about the README itself. I'm also not a Flutter guru, just your average joe with some years on my belt.

1. README Yes, it's not written in a perfectly "professional" manner, yes many sentences can be formulated better, yes at times the "tone" might sound like "this is great you should try it you get this and that X benefits" and if you've been doing this for so long you'd normally close the browser tab and go back to your professionally documented X module, or whatever, that simply works instead of risking it.

But that wasn't what I did, I instead decided to give it a go, and the reason for that is simple: It's written from the heart by an unlikely guy who's English is not even is his first language. For all that I care, he could've written an essay about flowers, ice-cream and unicorn milk and I would've still opted to give it a try.

2. What was I looking for

  1. Get rid of all of the noise which in my opinion should've been baked under the hood into Flutter, including StatefulWidgets, "builders" or what not so I could keep my code minimal.
  2. Bugs, syntax sugar are fine as long as they are predictable - the code is readable there's no hidden magic in there, any pain points are clearly visible or can be worked around. Happy to trade those for performance and improved productivity.

3.Does it deliver? I have been using MobX for over a year (both backend and Flutter), and Provider for half a year. I love them both, the maintainers of MobX Dart are wonderful, responsive to issues and concise. Provider just works not a single negative word I can say about it. If anything, I'm grateful they exist.

But I did end up switching over to Get. @jonataslaw must be doing something right, and maybe, just maybe it's the imperfect README.

Imho, this issue should be closed and everyone should move on, we live at moment of time in history when we should be thankful for whatever contribution each person is doing to help others, be Get, Provider, packageX, Y or Z.

Peace.

I just stumbled upon this issue, only been using Get less than a day, and my background is similar to that of @stefandevo's, mostly back-end, high obsession with minimal reusable modular code.

I rarely, if ever, comment on anything that is not directly related to code but I feel I need to share my personal experience, also about the README itself. I'm also not a Flutter guru, just your average joe with some years on my belt.

1. README Yes, it's not written in a perfectly "professional" manner, yes many sentences can be formulated better, yes at times the "tone" might sound like "this is great you should try it you get this and that X benefits" and if you've been doing this for so long you'd normally close the browser tab and go back to your professionally documented X module, or whatever, that simply works instead of risking it.

But that wasn't what I did, I instead decided to give it a go, and the reason for that is simple: It's written from the heart by an unlikely guy who's English is not even is his first language. For all that I care, he could've written an essay about flowers, ice-cream and unicorn milk and I would've still opted to give it a try.

2. What was I looking for

  1. Get rid of all of the noise which in my opinion should've been baked under the hood into Flutter, including StatefulWidgets, "builders" or what not so I could keep my code minimal.
  2. Bugs, syntax sugar are fine as long as they are predictable - the code is readable there's no hidden magic in there, any pain points are clearly visible or can be worked around. Happy to trade those for performance and improved productivity.

3.Does it deliver? I have been using MobX for over a year (both backend and Flutter), and Provider for half a year. I love them both, the maintainers of MobX Dart are wonderful, responsive to issues and concise. Provider just works not a single negative word I can say about it. If anything, I'm grateful they exist.

But I did end up switching over to Get. @jonataslaw must be doing something right, and maybe, just maybe it's the imperfect README.

Imho, this issue should be closed and everyone should move on, we live at moment of time in history when we should be thankful for whatever contribution each person is doing to help others, be Get, Provider, packageX, Y or Z.

Peace.

I just stumbled upon this issue, only been using Get less than a day, and my background is similar to that of @stefandevo's, mostly back-end, high obsession with minimal reusable modular code.

I rarely, if ever, comment on anything that is not directly related to code but I feel I need to share my personal experience, also about the README itself. I'm also not a Flutter guru, just your average joe with some years on my belt.

1. README Yes, it's not written in a perfectly "professional" manner, yes many sentences can be formulated better, yes at times the "tone" might sound like "this is great you should try it you get this and that X benefits" and if you've been doing this for so long you'd normally close the browser tab and go back to your professionally documented X module, or whatever, that simply works instead of risking it.

But that wasn't what I did, I instead decided to give it a go, and the reason for that is simple: It's written from the heart by an unlikely guy who's English is not even is his first language. For all that I care, he could've written an essay about flowers, ice-cream and unicorn milk and I would've still opted to give it a try.

2. What was I looking for

  1. Get rid of all of the noise which in my opinion should've been baked under the hood into Flutter, including StatefulWidgets, "builders" or what not so I could keep my code minimal.
  2. Bugs, syntax sugar are fine as long as they are predictable - the code is readable there's no hidden magic in there, any pain points are clearly visible or can be worked around. Happy to trade those for performance and improved productivity.

3.Does it deliver? I have been using MobX for over a year (both backend and Flutter), and Provider for half a year. I love them both, the maintainers of MobX Dart are wonderful, responsive to issues and concise. Provider just works not a single negative word I can say about it. If anything, I'm grateful they exist.

But I did end up switching over to Get. @jonataslaw must be doing something right, and maybe, just maybe it's the imperfect README.

Imho, this issue should be closed and everyone should move on, we live at moment of time in history when we should be thankful for whatever contribution each person is doing to help others, be Get, Provider, packageX, Y or Z.

Peace.

Thanks for this incredible comment, I agree with everything, and English is not my first language, in fact people in my country have a bad habit of never learning English, some people even open issues in Portuguese here and I edit them on their own of this. I am learning English after my old age, due to countless job offers that I had to refuse because of my basic English, and I may at some point be expressing myself badly, for not knowing how to say it any other way. I hope to improve both the organization of the documentation and the description of the package and its resources.

1N50MN14 commented 4 years ago

(you're welcome) Oh I didn't realize you're from Portugal, you're not far from me then, come to Sweden :)

On a side note, the comment about MediaQuery.of(context).size.height is super correct and valid I was going to open an issue about it later tonight (and follow up on the fade transition) as I rely on both width and height for all kids of responsive layering, it took me a whole hour to narrow it down to Get.

Those are the only two obstacles I'm facing, no issues otherwise ;)

rrousselGit commented 4 years ago

but I definitely didn't write with the intention of saying that StatefulWidgets should be abandoned, but with the intention of saying that it is the exception, not the rule.

That's my point.

I understand that it's not what you tried to say, but the wording caused people to think so.

To quote some reactions from reddit that are not from me:

This is the kind of reactions that I'm targeting when I say that I have a problem with the readme.

There is some truth in your statements, but the way they are exaggerated them makes it looks scary

For example, I believe that the entire discussion about RAM and performance could be removed. Instead publish your benchmarks and use that as a proof.

I would have done that before, but I don't know if this is ethical, because perhaps it would detract from the work of the last positions of StateManager.

I don't see it as unethical.

I would argue that it is the opposite in fact. Having your benchmarks private-sourced, and then make statements like "Get consume less memory" without showing any proof is bad.

But if it is open source, you merely exposed a fact. People can run the benchmarks themselves to see that it is true. And maintainers can contribute to the benchmarks. Maybe some things can be optimised in the benchmark. Maybe these packages can be optimised.

I think everyone would benefit from this. If people attack you for it, I will take responsibility and defend you.

I'm not pretentious, and I didn't write anything like that in the readme.

Multiple people have reported the perception that it is pretentious.

In addition, here are some quotes to your comment on reddit:

These are not very modest statements.

These quotes are part of the reasons why I got angry at Get to be honest, combined with the confusion caused in the readme.

But anyway, like I said I apologise for being rude.

jonataslaw commented 4 years ago

but I definitely didn't write with the intention of saying that StatefulWidgets should be abandoned, but with the intention of saying that it is the exception, not the rule.

That's my point.

I understand that it's not what you tried to say, but the wording caused people to think so.

To quote some reactions from reddit that are not from me:

  • I'm sorry but the ReadMe doesn't sell me, a lot of bold and inaccurate statements.

  • It looks very simple. But the following line from readme threw me off:

    Using StatefulWidgets means storing the state of entire screens unnecessarily. With Get the use of StatefulWidget is optional. Avoid them and save your users' RAM.

    Who is teaching these?!

  • That readme spread so many false information

  • Holy moly! Is StatefulWidgets really that scary?

This is the kind of reactions that I'm targeting when I say that I have a problem with the readme.

There is some truth in your statements, but the way they are exaggerated them makes it looks scary

For example, I believe that the entire discussion about RAM and performance could be removed. Instead publish your benchmarks and use that as a proof.

I would have done that before, but I don't know if this is ethical, because perhaps it would detract from the work of the last positions of StateManager.

I don't see it as unethical.

I would argue that it is the opposite in fact. Having your benchmarks private-sourced, and then make statements like "Get consume less memory" without showing any proof is bad.

But if it is open source, you merely exposed a fact. People can run the benchmarks themselves to see that it is true. And maintainers can contribute to the benchmarks. Maybe some things can be optimised in the benchmark. Maybe these packages can be optimised.

I think everyone would benefit from this. If people attack you for it, I will take responsibility and defend you.

I'm not pretentious, and I didn't write anything like that in the readme.

Multiple people have reported the perception that it is pretentious.

In addition, here are some quotes to your comment on reddit:

  • In addition, Get is the only intelligent state manager that exists.

  • At some point in time, Get will become one of the most used packages in the world with Flutter (it already is, but I say something about top 3)

These are not very modest statements.

These quotes are part of the reasons why I got angry at Get to be honest, combined with the confusion caused in the readme.

But anyway, like I said I apologise for being rude.

Well, I am not going to answer that to not extend this discussion further. Ask me a question, is there a more "performance" way of doing this with Provider?

class AppState with ChangeNotifier {
  List<Item> _items = sampleItems;
  List<Item> get items => _items;

  void addItem(Item item) {
    _items.add(item);
    notifyListeners();
  }
}
class ListViewWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<AppState>(
      builder: (context, state, child) {
        return ListView.builder(
          padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
          itemCount: state.items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(state.items[index].title),
            );
          },
        );
      },
    );
  }
}

I haven't used the provider in a long time, so if there's a way to do this that performs better, let me know. I'm going to make a separate repository, and mention it in the Get readme, the owners of the respective packages will be able to make modifications to use the best approach, and since you're already here, I didn't understand the context.watch from version 4, and I don't know if it is better or worse than the consumer.

rrousselGit commented 4 years ago

It depends on the list length I guess, but you could do:

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
      itemBuilder: (context, index) {
        return Builder(builder: (context) {
          final title = context.select((AppState s) {
            if (index >= s.items.length) return null;
            return s.items[index].title;
          });

          if (title == null) return null;
          return ListTile(title: Text(title));
        });
      },
    );
  }
}

Although it may be more performant to return the Item in the selector instead of title. It depends on how the item class is implemented.

Nipodemos commented 4 years ago

Wow this escalated to something way beyond this issue, but it is good it is solved.

I wanna help with the documentation, so if you are making changes, please put them in another branch so i can help while you doing it.

This issue can be closed now i suppose πŸ˜…

murilosandiego commented 4 years ago

@jonataslaw, this CLI is like a Slidy

jonataslaw commented 4 years ago

@jonataslaw, this CLI is like a Slidy No, Slidy works with internal modules and models, this CLI will work with external models

1N50MN14 commented 4 years ago

Hey guys, I was very frustrated I'm unable to find a standalone, super slim state management package that doesn't use generators, doesn't kill my CPU or get in the way for me - get got very close (the implementation is surprisingly close to that of observable_ish) but there are too many things going under the hood for my needs.

Anyway, I ended up writing one myself out of frustration, under 220 lines in total, super slim, super fast and makes it possible to handle deeply nested properties without a single unnecessary rebuild.

@rrousselGit @jonataslaw I'd very much be thankful if it was possible for you to take a quick look https://github.com/1N50MN14/nuke - I just pushed it to github (not published on pub.dev to avoid any embarrassments) and let me know what you think...

@rrousselGit I had Provider on the back of my mind while writing it, the idea is to throw it at the root of the app since it's very slim, and it'll tidy up after itself thereafter. Would really appreciate your feedback on any flaws you may find...

Here's how the counter app looks like:


import 'package:nuke/nuke.dart';

class MyHomePage extends StatelessWidget
{
  final counter = 0.rx|'counter';

  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context)=>Scaffold
  (
    appBar: AppBar(),
    body: Center
    (
      child: $Rx(const ['counter'], (ctx)=>Text('${'counter'.get.value}'))
    ),
    floatingActionButton: FloatingActionButton
    (
      onPressed:()=>'counter'.get.value++,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}```
Nipodemos commented 4 years ago

@1N50MN14 Hey! i am by no means someone who can analyze your code, but i got curios by your syntax choices: final counter = 0.rx|'counter';

Edit: i only noticed now that you explained some of my doubts in your readme πŸ˜… Now i have other question: why do you need to get counter of two different ways in order for you observable to change state?

jonataslaw commented 4 years ago

Hey guys, I was very frustrated I'm unable to find a standalone, super slim state management package that doesn't use generators, doesn't kill my CPU or get in the way for me - get got very close (the implementation is surprisingly close to that of observable_ish) but there are too many things going under the hood for my needs.

Anyway, I ended up writing one myself out of frustration, under 220 lines in total, super slim, super fast and makes it possible to handle deeply nested properties without a single unnecessary rebuild.

@rrousselGit @jonataslaw I'd very much be thankful if it was possible for you to take a quick look https://github.com/1N50MN14/nuke - I just pushed it to github (not published on pub.dev to avoid any embarrassments) and let me know what you think...

@rrousselGit I had Provider on the back of my mind while writing it, the idea is to throw it at the root of the app since it's very slim, and it'll tidy up after itself thereafter. Would really appreciate your feedback on any flaws you may find...

Here's how the counter app looks like:

import 'package:nuke/nuke.dart';

class MyHomePage extends StatelessWidget
{
  final counter = 0.rx|'counter';

  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context)=>Scaffold
  (
    appBar: AppBar(),
    body: Center
    (
      child: $Rx(const ['counter'], (ctx)=>Text('${'counter'.get.value}'))
    ),
    floatingActionButton: FloatingActionButton
    (
      onPressed:()=>'counter'.get.value++,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}```

Dude, congratulations on your work. It looks very promising. I will definitely look more calmly when I have time, but it seemed very interesting.

rrousselGit commented 4 years ago

@1N50MN14 Interesting idea.

I'd be very careful with manipulating string though. You are losing the benefits of Dart being statically typed. It could be problematic for larger codebases/teams. Renaming 'counter' and avoiding typos could be difficult

1N50MN14 commented 4 years ago

Hey @Nipodemos :) I was just about to hit the sack, will answer quickly: 1- The reason for $Rx is that I needed a short name, out of the way as much as possible so I could focus on the actual widget itself. The $ is to avoid any potential naming conflicts just in case someone decided to use the package since "Rx" is short.

2- The observers you don't need to get/set them twice, in the readme I showed two different ways of setting/getting values, you can either do that within a class using getters/setters or by reference - imagine doing that in a deeply nested observable - I had a change of heart about mobx when I realized it renders the whole thing, Get actually does a good job in a sense that it keeps track of timestamps on collection items. My approach is a bit different, by relying on references observables can be placed anywhere, and regex matchers to narrow down what should listen to what.

But it'll also allow for crazy stuff, like computed values from different models spread around the app - even if model instance are destroyed until no subscribers are available.

(About to fall asleep here will be back later but I hope this explains abit)

1N50MN14 commented 4 years ago

Oh I think the 'counter' is a source of confusion (I'll update readme), this could've been 'counter/0' so if you have another counter with a reference 'counter/1' you could either bind a widget to either, both or 'counter/: index'. The the | is actually an operation extension on the Nuke's observable - it looks as if it's on the String only because it's chained, just a little trick which I thought looked neat 😁

1N50MN14 commented 4 years ago

Nevertheless it's a great feedback, I have 3 extension methods will review them again tomorrow.. thank you (and thank you @jonataslaw just saw it)

Renaming 'counter' and avoiding typos -- that's a very good point actually, I didn't think about it (I was more thinking the case of "banana republic counter app" example) hmmm good point

1N50MN14 commented 4 years ago

@Nipodemos @rrousselGit @jonataslaw

Thanks again for the feedback, I made modifications to the API based on that, here's how it looks now:

import 'package:nuke/nuke.dart';

class MyHomePage extends StatelessWidget
{
  final counter = 0.$at.$ref('ref/0');

  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context)
  {
    return Scaffold
    (
      body: Center
      (
        child: $RX
        (
          matchers: const ['ref/0'],
          builder: (context) => Text($ref('ref/0').value.toString())
        )
      ),
      floatingActionButton: FloatingActionButton
      (
        onPressed: ()=>$ref('ref/0').value++,
        child: const Icon(Icons.add),
      ),
    );
  }
}

EDIT: Ofcourse in the above example one could still do counter.value instead of $ref('ref/0').value - but the nice thing is that using $ref counter doesn't even need to live inside the widget so one can reference multiple values from multiple Widgets in multiple places around the app!

A practical example would be a "Settings" screen where value X is utilized in the underlying widget (assuming it's not disposed), this saves the hassle of passing values between the two and updating each's local state.

@rrousselGit Instead of extending on String (this was a really good point) I'm now wrapping observables in a reference class (with cached instances).

@Nipodemos matchers and builder are now named parameters, I also placed a small note in README about the usage of $, $Rx -> $RX (just because it looked nicer, visually), got rid of the | operator replaced with .$ref which is more readable, $rx now reads $at. :-)

@jonataslaw So basically the way this code can be extended is by detecting the value, if it's a future then resolve it, if it's a Stream then pipe it to the correct reference, pause() resume() to emulate throttling / debounce etc - BUT I think it will shine with collections and maps because elements live in their own scope, for example, the observer widget can be configured in away if value is null then a SizedBox.shrink() is displayed instead of that could indicate a "message" has been delete completely up to the user what to do with. Ofcourse that leaves plenty of room for fuck ups, but then the code deserves to break. Please feel free to shime in or use any of the concepts, but I think it'd be great if we could built on that direction.

Ugh forgot to change the license.md to WTFPL

Nipodemos commented 4 years ago

@1N50MN14 hello! Actually I think I wrote poorly one of my questions I am wondering why you need the paremeter "matcher" in the $rx widget. I mean, you are already using the $ref inside the builder, You are explicitly saying that the text widget content is the $ref with the specified key, the matchers are really needed? That's what I meant when I asked why the counter is in two places

Remember I am wondering that but I don't understand almost nothing about the complexity of state managers, so sorry if this question is silly πŸ˜…πŸ˜…

rrousselGit commented 4 years ago

@jonataslaw Do you think you could post a zip of your benchmarks in this issue? I'd like to try them myself.

loicgeek commented 4 years ago

@jonataslaw @rrousselGit I feel very bad when I see you fighting among yourselves, we who take you as models.

1N50MN14 commented 4 years ago

@Nipodemos There are two reasons for that: In doing so, you can declare counter outside the widget and let any other widget listen to it, for example today I used DateTime.now().$at.$ref('device/resize') which basically timestamps the value every time the context's width / height / orientation changes. It's placed on top my widget tree.

Now, instead of wrapping root widgets with $RX, I just wrapped the specified Text element which I wanted to scale up / down - nothing else got rebuilt, just that little widget, to do that, I have

nuke.subscribe('controller.ui.on.device/resize', ['device/resize'], (_)=>calculateScaleFactor()) 

(which basically sets the new scale factor as an observable)

And I'm using the scale factor everywhere I need by reference in multiple widgets without needed to declare it in all of them ;)

The second reason for that is, let's say you have counter1 in one widget, counter2 in another widget and a third widgets that calculates the sum of the two - you could do that by reference without needing to build a class the holds the variables and share it among three different widgets ;)

jonataslaw commented 4 years ago

@jonataslaw Do you think you could post a zip of your benchmarks in this issue? I'd like to try them myself.

I will post when I remake the Banner, Felix pointed out something to me, 150kb is written 1.5mb, the ratio is still correct, but the description is wrong, I will correct it and post it in the readme. I'm looking for a way to take the print or the memory consumption automatically, but it is difficult to find a solution that does this.

If you have any ideas, I would appreciate it.

jonataslaw commented 4 years ago

@jonataslaw @rrousselGit I feel very bad when I see you fighting among yourselves, we who take you as models.

I am not fighting with Remi. I have respect for him and the work he has already done. At least on my part everything is fine.

jonataslaw commented 4 years ago

https://github.com/jonataslaw/benchmarks

This repository has the benchmarks. The banner has the correct metrics, but is being measured in the wrong measure. Read 1 as 100kb. Anyone who wants can start the application in --profile mode and test it on their own.

sardapv commented 3 years ago

@jonataslaw @rrousselGit Guys, you two are legends in flutter community. Both of you solved problems to every extent possible. And you are heroes in community where people are still struggling to find best state manager. Honestly. I tried provider first as it was recommended in course I did on udemy. I liked it, I tried GetX 2 days ago and I like it too.. Get just simplifies and converts code syntax to normal language (Dart and flutter boilter plate is too confusing to write). Respect for you two <3 I came to this thread from youtube :P and read entire discussion here and learnt a thing or two :P