I have this piece of code that intend to use in a stateless widget in flutter.
const String default_question = 'the question';
class Trial {
final String question;
const Trial.standard() :
question = default_question;
}
I use it like this:
final Trial _trial = const Trial.standard();
And this works. But it doesn't work without using const. And I want to understand why const is neccessary here. Because I plan on using a constructor that is not constant in the future.
-----------EDIT---------------
So I had a deeper look into the problem. My IDE linked the error to sauce. Which made me realise that the problem had nothing to do with trial but with the constructor for the stateless widget that I was using. The constructor that I had for the stateless widget was a constant costructor, I think that that is a default configuration voor creating a new stateless widget with my IDE. So I just removed the const keyword there and now I can declare variables in that widget that are not constant.
I'm not sure if a non constant constructor for a stateless widget is bad practice in flutter, but for now it makes sense to me.
cosnt marked widgets or variables are built only once in flutter framework which helps in performance improvement.
And this is done by a packages flutter_lints which is added in pubspec.yaml by default in latest flutter versions. You can check docs at given at flutter official website.
If you don't want to use this thing, simply remove the package from pubspec.yaml
Cheers!
Related
Please see the question above. I looked the documents, but didn't find any answers.
It depends on the child/ children if they don't have static value it can't be const. if the have hardcoded or static values then it must be const
Why do we need to use const widgets in flutter?
It is recommended to use const constructors whenever possible when creating Flutter widgets. The reason is the performance increase since Flutter can save some calculations by understanding that it can reuse that widget from a previous redraw in the current one since it is a constant value.
Flutter has a special treat for when the instance of a widget doesn't change: it doesn't rebuild them.
Consider the following:
Foo( child: const Bar( child: Baz() ), )
In the case of the build method being called again (setState, parent rebuild, Inheritedwidget...), then due to the const for Bar subtree, only Foo will see its build method called.
The bar will never get rebuilt because of its parent because Flutter knows that since the widget instance didn't change, there's nothing to update.
Why can't we make a Container widget and Column widget const?
You cannot make const a Container as the Constructor of Container is not const that's why it won't let you do it.
This is allowed in the form of making the children const. Allowing const on the children means they will not rebuild if they are not dynamic.
Flutter doesn't rebuild widgets that are marked created through const constructor and the main part of the flutter widgets supports const constructors. Except for Column and Row and other multi-child layout widgets.
Do we really need to make multi-child layout widgets const?
The Column/Row themselves do not need to be const as they're only for laying out the widgets, it's the children that need to const. The same behavior applies to the rest of the Multi child layout widgets.
These might be for lots of reasons. Instead of listing all of them here. I will show you how to explore each one of them on your own so that you can orient your investigations based on your needs. Below, are the steps I went through to figure out why the container is non-const. (you can do this with any other Widget or constructor)
Explore the source code
Open the fuller package (in VSCode): [flutter_location]/packages/flutter/lib/src/widgets/container.dart
Run flutter pub get
Look for the Container constructor
Add the const keyword in front of it
All elements that prevent the Container from being a const constructor, quite a few, will show errors!
To explore multiple widgets at once just open the entire folder [flutter_location]/packages/flutter. Then run flutter pub get.
I often see people talking about using riverpod when defining dependencies for each class in flutter.
final apiClientProvider = Provider.autoDispose(
(_) => GithubApiClientImpl(),
);
final githubRepositoryProvider = Provider.autoDispose(
(ref) => GithubRepositoryImpl(ref.read(apiClientProvider)),
);
final repositoryListViewModelProvider = StateNotifierProvider.autoDispose(
(ref) => RepositoryListViewModel(ref.read(githubRepositoryProvider)),
);
However, I do not understand the benefits of why it is a good idea to use riverpod.
Shouldn't it be initialized at the time of use as shown below?
I feel that the following writing style is sufficient in terms of testing, for example, you can initialize the mock with a test file.
final githubRepository = GithubRepositoryImpl(GithubApiClientImpl());
final repositoryListViewModel = RepositoryListViewModel(GithubRepositoryImpl(GithubApiClientImpl()));
Why bother using riverpod?
1 - there is nothing that gets initialized out of the box it get initialized first time someone request it for example ref.read(fooProvider)
the docs:
https://docs-v2.riverpod.dev/docs/concepts/providers#creating-a-provider
Do not be frightened by the global aspect of providers. Providers are fully immutable. Declaring a provider is no different from declaring a function, and providers are testable and maintainable.
2 - for mocking you can override a provider see the docs for more info
https://docs-v2.riverpod.dev/docs/cookbooks/testing#overriding-the-behavior-of-a-provider-during-tests
Is it possible to extend a widget? take for instance the CalendarDatePicker widget. I like the existing features but I want to be able to extend it.
I want to be able to have a little dot under each day that has some events whether it is just one or multiple events. If a day doesn't have any events, then nothing needs to show under that day. Events would be coming from a firebase Firestore.
The reasons are:
I like the CalendarDatePicker and I prefer not having to install a new package. I see people are using Table_Calendar. It is nice but I am trying to reuse leverage what is already there and stay away from installing too many packages.
I'd prefer not to design one from scratch when there is one that already does 98% of what needs to get done.
Thanks
You can extend widgets and override its properties and methods with extends keyword (see docs). It is simple OOP inheritance. But anyway you should fully override build method to complement existing UI. Do it, copy existing code from CalendarDatePicker build method to you custom class build method and update this code as you wish:
class CustomDatePicker extends CalendarDatePicker {
const CustomDatePicker({
Key? key,
// here you can use constructor properties that you need
// and pass them to superclass constructor
}) : super(...);
#override
Widget build(BuildContext context) {
// use code from CalendarDatePicker build method
// and update it as you wish
}
}
So I was wondering about the Command I use when I close an AlertDialog:
FlatButton(
child: Text('Okay'),
onPressed: () {
Navigator.of(context).pop();
},
),
What does .of() exactly do? I could not find anything in the flutter dev documentation (Probably because I was missing the correct search term)
Can anyone explain what happens there?
In the Flutter SDK the .of methods are a kind of service locator function that take the framework BuildContext as an argument and return an internal API related to the named class but created by widgets higher up the widget tree. These APIs can then be used by child widgets to access state set on a parent widget and in some cases (such as Navigator) to manipulate them. The pattern encourages componentization and decouples the production of information related to the build tree with its consumption.
In addition to Navigator.of (returns a NavigatorState) there are:
Theme.of (returns a ThemeData containing the ambient theme settings)
MediaQuery.of (returns a MediaQueryData containing information computed about the device screen size)
Directionality.of (returns a TextDirection containing information about text display)
Of course Flutter has non-specific methods for looking up parent widgets from the build context:
context.findAncestorWidgetOfExactType<T extends Widget>()
context.findAncestorStateOfType<T extends State>()
context.findRootAncestorStateOfType<T extends State>()
so Theme.of(context) is really just a static shorthand for context.findAncestorWidgetOfExactType<Theme>().data and Navigator.of(context).pop() is really just a shorthand for context.findAncestorStateOfType<NavigatorState>().pop()
From the documentation of the Navigator class,
Although you can create a navigator directly, it's most common to use the navigator created by the Router which itself is created and configured by a WidgetsApp or a MaterialApp widget. You can refer to that navigator with Navigator.of.
As a general rule, any time you see something along the lines of Classname.of(someObject) in an OO language, .of is a builder that returns an instance of Classname from someObject.
I am using Provider. I have got two classes: class TenderApiData {} it's stand alone class (not widget). How I can write accesstoken to AppState?
class AppState extends ChangeNotifier // putted to ChangeNotifierProvider
{
String _accesstoken; // need to fill not from widget but from stand alone class
String _customer; // Fill from widget
List<String> _regions; // Fill from widget
List<String> _industry; // Fill from widget
...
}
I need way to read\write accesstoken from stand alone classes.
Or I have issue with architecture of my app?
Here is full source code.
You cannot and should not access providers outside of the widget tree.
Even if you could theoretically use globals/singletons or an alternative like get_it, don't do that.
You will instead want to use a widget to do the bridge between your provider, and your model.
This is usually achieved through the didChangeDependencies life-cycle, like so:
class MyState extends State<T> {
MyModel model = MyModel();
#override
void didChangeDependencies() {
super.didChangeDependencies();
model.valueThatComesFromAProvider = Provider.of<MyDependency>(context);
}
}
provider comes with a widget built-in widgets that help with common scenarios, that are:
ProxyProvider
ChangeNotifierProxyProvider
A typical example would be:
ChangeNotifierProxyProvider<TenderApiData, AppState>(
initialBuilder: () => AppState(),
builder: (_, tender, model) => model
..accessToken = tender.accessToken,
child: ...,
);
TL;DR
Swap provider for get_it. The later does DI globally without scoping it to a BuildContext. (It actually has its own optional scoping mechanism using string namedInstance's.)
The rest...
I ran into a similar problem and I believe it comes down to the fact that Provider enforces a certain type of (meta?) architecture, namely one where Widgets are at the top of what you might call the "agency pyramid".
In other words, in this style, widgets are knowledgable about Business Logic (hence the name BLoC architecture), they run the show, not unlike the ViewController paradigm popularised by iOS and also maybe MVVM setups.
In this architectural style, when a widget creates a child widget, it also creates the model for the widget. Here context could be important, for example, if you had multiple instances of the same child widget being displayed simultaneously, each would need its own instance of the underlying model. Within the widget or its descendents, your DI system would need the Context to select the proper one. See BuildContext::findAncestorWidgetOfExactType to get an idea why/how.
This architectural style is the one seemingly encouraged by plain vanilla Flutter, with its paradigms of app-as-a-widget ("turtles all the way down"), non-visual widgets, layout-as-widgets and InheritedWidget for DI (which provider uses I believe)
BUT
Modern app frameworks libs (e.g. redux, mobx) encourage the opposite kind of meta-architecture: widgets at the bottom of the pyramid.
Here widgets are "dumb", just UI signal generators and receivers. The business logic is encapsulated in a "Store" or via "Actions" which interact with a store. The widgets just react to the relevant fields on the store being updated and send Action signals when the user interacts with them.
Which should you use?
In my experience, at least on mobile where the screen realestate is less, scoping a model to a branch in the render tree is seldom required. If it suddenly becomes important then there are plenty of other ways to handle it (indexed array, id lookup map, namedInstances in get_it) than to require linking it to the semantics of UI rendering.
Currently, having spent too much time in iOS ViewControllers, I'm a fan of new systems which enforce better SoC. And personally find Flutter's everything-is-a-widget pardigm to appear a bit messy at times if left untended. But ultimately it's a personal preference.
you can use navigator key
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
and put this key in MaterialApp and wrap it with your provider (TenderApiData)
ChangeNotifierProvider<TenderApiData>(
create: (_) => TenderApiData(),
child: Consumer<TenderApiData>(builder: (context, tenderApiData , child) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'title',
home: SplashScreen());
}),
);
and listen to this provider from anywhere with this navigator key
navigatorKey.currentContext?.read<TenderApiData>();