-
-
Notifications
You must be signed in to change notification settings - Fork 153
[Marketing and API] Improvement suggestions for get_it and get_it_mixin #246
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
Comments
Ya I agree with a lot that is said here:
|
I think there are a couple of threads here that we can probably split out:
I agree that the naming is not the most communicative, in some sense all the users really want to know about is It's probably fine that it continues to exist as it's own package with it's current name, as long as, from the |
Also, @dancamdev I'd like to get your feedback on the new proposed readme for GetIt (short-term solution to some of these problems): |
Sure, I'll have a look at the read me ASAP. I opened this issue to sum up a few of my thoughts, it's definitely worth splitting them into multiple ones, each one focusing on a specific topic. |
General API thoughts, just to get them out there:
This feels most natural to me: The override proposal looks nice, but I'm not sure it will work properly without specifying generics for each type, which isn't much of an improvement in the end.
You actually lost a line over the manual push... it's also less clear what is actually happening. /shrug. If anything, maybe @escamoteur It would be nice to know if you think we can get rid of watch, watchOnly, watchXOnly and replace with just contextual
I don't really understand all the various use cases enough to say, nor the level of effort required to implement things this way :D |
This would also address one of my main annoyances with the mixin now: I usually set up getters for my singletons, like Would be kinda cool if this could all be consolidated:
This could be re-written without my helper methods as:
This would be accomplished by adding extension methods to the various types that the mixin supports (ValueListenable, Future etc). In this case |
well, fwiw, I tried to do a proof of concept and immediately found a dart compiler bug :D |
Would love to pick up the discussion where we left it off, I'm planning to contribute more on this issue. |
Hi, I haven't forgotten this. I will try to get back to it after vacation |
@escamoteur would be great to have your feedback on this! |
Hi, I'm sorry for the long time. I have to reread all the discussion again. |
I definitely am open to a renaming of the methods, even add some more that are easier to use with less parameters. |
After spending time with Provider, Riverpod, and GetX state management, I recently discovered Get It + Get It Mixin and feel like it's a super-elegant solution. I agree that merging these packages makes things a lot clearer for someone that is new to this. |
@cliftonlabrum if you want to get involved more, I'm happy about any hand that joins the effort. |
@escamoteur I'm still fairly new to Flutter, so I'm unsure how much dev help I can provide, but I can help with design and documentation. Are you considering an entirely new name? I always thought it a touch confusing that there is GetX and GetIt in Flutter, but they are entirely different. 😅 If you are open to new names, what about
|
Yeah, the name conflict with getX is annoying. get_it is much older than getX. But especially on documentation and feedback from a normal users view will be helpfull.
|
I also have an idea for simplifying the API in widgets. Let's say I have a GetIt getIt = GetIt.instance;
getIt.registerSingleton(UI()); My class UI extends ChangeNotifier {
//+++
static UI get to => getIt<UI>();
//+++
bool darkMode = true;
String accentColor = 'blue';
int unreadCount = 0;
} If I want to watch three properties from my class in a widget, I could do this: class MyWidget extends StatelessWidget with GetItMixin {
MyWidget({ Key? key }) : super(key: key);
@override
Widget build(BuildContext context) {
//+++
final darkMode = watchOnly((UI data) => data.darkMode);
final accentColor = watchOnly((UI data) => data.accentColor);
final unreadCount = watchOnly((UI data) => data.unreadCount);
//+++
return Container(
color: darkMode ? Colors.black : Colors.white,
etc.
);
}
} Or sometimes I do it like this: class MyWidget extends StatelessWidget with GetItMixin {
MyWidget({ Key? key }) : super(key: key);
@override
Widget build(BuildContext context) {
//+++
watchOnly((UI data) => data.darkMode);
watchOnly((UI data) => data.accentColor);
watchOnly((UI data) => data.unreadCount);
//+++
return Container(
color: UI.to.darkMode ? Colors.black : Colors.white,
etc.
);
}
} But if I have several properties to watch, and all I had to do was pass the name of the variables, I think that could be even simpler: class MyWidget extends StatelessWidget with GetItMixin {
MyWidget({ Key? key }) : super(key: key);
@override
Widget build(BuildContext context) {
//+++
watch([UI.to.darkMode, UI.to.accentColor, UI.to.unreadCount]);
//+++
return Container(
color: UI.to.darkMode ? Colors.black : Colors.white,
etc.
);
}
} I'm sure there could be an even more succinct way to handle it without the Just my perspective after a few days with Get It. 😄 |
I think in the cases where you use the value of the field you are watching (almost always?), it would be good practice to encourage them to store off the value, otherwise it would be quite easy to forget to bind to the method and then create a bunch of hard to spot bugs. eg, If you do it like this, nothing can break: final count = watchOnly((UI data) => data.unreadCount);
final accent = watchOnly((UI data) => data.accentColor);
return Text(count, style: TextStyle(color: color); Where as this is more brittle: watchMultiple((UI data) => [data.unreadCount, data.accentColor]);
return Text(data.unreadCount.value, style: TextStyle(color: data.accentColor.value); It is easy to omit the Seems like saving a cpl lines here is not worth the increased likelihood for bugs, |
while experimenting on how to realize a GetItWidget that could be (here is the part of flutter_hooks https://github.com/rrousselGit/flutter_hooks/blob/c89f05fa24e699f3d478bc87aad4df770f160e56/packages/flutter_hooks/lib/src/framework.dart#L414) With this trick hook functions can be normal functions and still access the hookstate object. We could do the same, which would reduce the amount of code of the mixin because we wouln't need two mixins (one for stateless and one for stateful widgets) to make the watch functions accessible. If people want to continue use the mixins, they would only need mixins on the widgets and not a separate on the state. Possible drawbacks:
Does anyone of you see any potential problems? Instead of global functions we could add them as functions to GetIt like userName = GetIt.I.watchProperty( (UserManager m) => m.userName); the disadvantage of that would be that the get_it package would depend on Flutter. If we start with a completely new package name (like Remi di with Riverpod) that wouldn't matter. |
adding @kekland to the discussion |
@esDotDev @escamoteur It might potentially be possible to use something like https://pub.dev/packages/custom_lint to create lints to help users avoid situations where they can accidentally introduce some runtime bugs while using |
I might add, that if I want to update a lot of values from the properties of an object it's probably more readable to watch the whole object and return it. |
cc) albertodev01 |
@esDotDev @kekland @dancamdev I would be interested in your opinion in #246 (comment) |
Ok, decided to keep it tow seperate packages, but the mixin gets renamed to Watch_it the simple state management powered by get_it :-) and we will overhaul the function names |
I think |
@esDotDev I will keep it two packages but watch_it will include get_it so you only have to import one package. |
Sounds great! Looking forward to the discussion on new method names as well. Seems like we could omit the final foo = watch<Foo>();
final bar = watchField((Foo f) => f.bar); It would be nice if that could be all we needed, and it could handle the various supported types, like Futures, Streams, ValueNotifiers, but not sure if that is doable with dart currently. |
I think that will be possible but it might be needed to pass some generic types in some cases. As the necessity to have more than one GetIt instance is pretty rare, |
can be closed now with the release of https://pub.dev/packages/watch_it |
Looks great! I'll make a blog post sometime soon on gskinner.com to try and raise a bit of awareness. Thanks Thomas! |
That would be awesome. I used your Readme as base and extended it a bit.
We switched today our whole project to it and the code looks so much better
Am 15. Juni 2023, 20:46 +0200 schrieb Shawn ***@***.***>:
… Looks great! I'll make a blog post sometime soon on gskinner.com to try and raise a bit of awareness. Thanks Thomas!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you modified the open/close state.Message ID: ***@***.***>
|
Uh oh!
There was an error while loading. Please reload this page.
This issue is a collection of thoughts I had when reading the gskinner article on their state management and DI solution using get_it and get_it_mixin. The main goal here is to have a discussion that could lead to improvements in the marketing and API aspects of the packages.
Some context on my experience with state management and flutter.
Get it & Get it mixin considerations
It’s not obvious how get it mixin is related to getIt (if at all).
People may not even know what a mixin is in dart and what it does. (You don’t need them that often in day to day flutter dev). Also the fact that it is a mixin doesn’t really help understand how it works.
My thesis here, is that people care a lot about the package name, in the end it’s the first clue on what the package does. GetitMixin doesn’t really tell me anything, apart that it’s related to getIt in some way, but do I know getIt?
Exporting getitmixin together with getIt could improve adoption.
Eventually changing get_it_mixin package name to a more descriptive name could help. (get_it_watchable).
API is great and simple, once you know how to access it. watchX() for example is not a really descriptive name unless you know where it’s coming from. (What does the X mean? Could we just have watch?
Even better would be if under the hood we’d use some extension and have something like:
Personally, as a user of other state management solution, the gskinner article helped me hugely to understand what this is all about, so maybe an improvement on the documentation explaining core concepts and how to use them with practical examples can benefit the package a lot as well.
The text was updated successfully, but these errors were encountered: