what is buildcontext in flutter? - flutter

What is the purpose of it in flutter framework?. I want to know the flow of build context.
class MyAwesomeWidget extends StatelessWidget{
#override
Widget build(BuildContext context)
return Container(
child: Text("Hello"),
);
}

According to some research as it says: "BuildContext is a locator that is used to track each widget in a tree and locate them and their position in the tree. The BuildContext of each widget is passed to their build method. Remember that the build method returns the widget tree a widget renders. Each BuildContext is unique to a widget."
So your all application is basically consist of tree structure and following it from the root of your app.

Related

Couldn't find the correct provider above this widget

I have a problem using Flutter Provider...
After Onbording screens I click to Next Button and needs to show me Welcome Screen (where i choose to log in with phone number)
But after clicking to Next Button i get this error - Could not find the correct Provider above this WelcomeScreen Widget
class _WelcomeScreenState extends State<WelcomeScreen> {
#override
Widget build(BuildContext context) {
final ap = Provider.of<AuthProvider>(context, listen: true);
return Scaffold(
body: SafeArea(
child: Center(
Make sure your Provider<> widget is present and at the root(like parent of MaterialApp for instance) to make sure it is in widget tree across rebuilds.
As far as I can see your code, you're calling Provider watch in welcome screen which prolly doesn't have the Provider in its tree. Move the watch to OnboardingScreen.

Differences between AnimatedBuilder and StatefulWidget in Flutter?

From my point of view, all animations continuously render the widget with some often-changed value. For example, a spinning hand on a clock has a value called 'angle' to indicate its position.
In Flutter, it seems that StatefulWidget is enough for it. My question is:
What functions do AnimatedBuilder/AnimatedWidget have?
What are the differences between AnimatedBuilder/AnimatedWidget and StatefulWidget?
I'll assume that AnimationBuilder is AnimatedBuilder because there is no such class as AnimationBuilder in the Flutter SDK.
Short answer
There are no differences besides the class names and the parameters.
Long answer
In Flutter, it seems that StatefulWidget is enough for it.
You are right.
What functions do AnimatedBuilder/AnimatedWidget have?
Nothing special, they are classes that exists only to wrap common/boilerplate code, see:
AnimatedWidget: flutter/lib/src/widgets/transitions.dart is simply a StatefulWidget that takes a listenable and triggers the setState whenever the listanable notifies a change.
The AnimatedBuilder: flutter/lib/src/widgets/transitions.dart is a subclass of ListenableBuilder which is a subclass of AnimatedWidget (!), the only difference is that AnimatedBuilder uses your callback as the build method of AnimatedWidget.
That being said, lets go to the code:
AnimatedBuilder is simply a StatefulWidget that uses your callback function (builder: (...) { }) as build method. It also triggers setState everytime the Listenable (animation) notifies a change.
Widget build(BuildContext context) {
return Center( // The [Center] widget instance will not rebuild.
child: AnimatedBuilder(
animation: animation,
builder: (context, child) {
return /* Widge tree that will rebuild when [animation] changes. */;
},
),
);
}
The equivalent code using AnimatedWidget is:
Widget build(BuildContext context) {
return Center( // The [Center] widget instance will not rebuild.
child: MyAnimatedWidget(animation: animation),
);
}
// ...
class MyAnimatedWidget extends AnimatedWidget {
const MyAnimatedWidget({required Listenable animation}) : super(listenable: animation);
Widget build(BuildContext context) {
return /* Widge tree that will rebuild when [animation] changes. */;
}
}
What are the differences between AnimatedBuilder/AnimatedWidget and StatefulWidget?
As I said, there is no semantic or real difference. AnimatedWidget and AnimatedBuilder are only abstractions of StatefulWidget.

How can I make a card clickable and navigate to another page inside TabBarView?

I'm trying to make a card clickable and navigate to another page 'forecastWeather.dart'. But I can't seem to figure out how I can fix the error I'm getting. The error message says
Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
I'm using a TabBarView with two tabs and one contains a card which should be clickable and navigate to another page 'forecastWeather.dart'. Please help!
In order to get use navigator.push, you must pass the context of your widget and have a MaterialApp somewhere in your tree, you do both, so the code should work, but it doesn't.
The reason is simple, the context you are passing is outdated, you are first creating the context when the build method begins, at that point, there is no material app, then you add a material app, but the context already exists, so the context you are passing when calling Navigator.push(context ... has no MaterialApp.
A possible fix is to use the Builder widget to make a new context after you create the MaterialApp widget:
#override
Widget build(BuildContext context) {
// context has no material app.
return MaterialApp(
home: Builder(
builder: (context) {
// this context does have a material app and is safe to use.
return DefaultTabController( ... );
}
),
);
}
Another fix is to move the code into a new widget with it's own context:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
// this context was created after the material app.
return DefaultTabController(...);
}
}
i suggest you to use get: ^4.6.1 package.
with this package you just need to use this for any navigation:
Get.to(ForecastWeather());
this package have so other features read its document here
[1]: https://pub.dev/packages/get

Flutter Widget building & structure

It seems there is a lots of way to build Widget in Flutter. It is a bit overwhelming to understand the right way of doing it. Can anyone explain me the difference between defining a variable inside/outside the build function as follow:
Inside class
class Login extends StatelessWidget {
TextFormField username() {
return TextFormField();
}
#override
Widget build(BuildContext context) {
return Scaffold();
}
}
Inside build function
class Login extends StatelessWidget {
#override
Widget build(BuildContext context) {
TextFormField username() {
return TextFormField();
}
return Scaffold();
}
And also is there is any difference between defining the variable as follow:
class Login extends StatelessWidget {
final username = TextFormField();
TextFormField username() {
return TextFormField();
}
#override
Widget build(BuildContext context) {
return Scaffold();
}
}
Thanks a lot for your help.
Jonathan.
There are several ways to do anything within the programming world. With Flutter / Dart it would be no different.
However, there are more "orthodox" ways of doing things, which will certainly save you from structural problems.
1- Declaration of an instance.
When you have a class that is not a widget, you usually use common instances of classes.
String name = "Jonny";
TextEditingController controller = TextEditingController();
When you declare widgets, there are 3 ways to do this, but only 1 is recommended.
The first is to store the widget in a variable (just like we did above).
final text = Text ('Pablo');
Build widget (BuildContext context) {
return Scaffold (body: text);
The second, and least recommended of all, is to create a method that gives you an instance of that widget
Widget text () {
return Text ('Pablo');
}
Build widget (BuildContext context) {
return Scaffold (body: text ());
This second approach is less recommended, because you will manufacture a new instance every time the method is called. If this widget has a heavy rendering, you are throwing resources in the trash.
The third (and highly recommended, I would tell you to stick to it and forget about it any other way) is nesting widgets in the tree:
Build widget (BuildContext context) {
return Scaffold (body: Text ('Pablo'));
This ensures that the same instance of Text () remains on the tree, and consequently if it were a much larger widget, this would be the most resource-efficient approach.
What if my tree becomes giant? how to avoid the ripple effect?
Simple, create new StatelessWidgets to break the tree's cascading effect.
Build widget (BuildContext context) {
return Scaffold (body: MyText());
class MyText extends StatelessWidget {
Build widget (BuildContext context) {
return Container (child:
Center (child: Text ('Pablo')),
);
}
}
Note: This was done for example purposes only, you must componentize reusable, or componentizable widgets, to avoid the effect:
aa
aaa
aaaa
aaaaa
aaaaaa
aaaaaaa
aaaaaaa
But if you have a few lines of code you don't have to worry about it as much.

Does whole subtree rebuilds on setState in flutter

I am new to flutter and really wondering if all the subtree of widgets gets rebuild when we call setState.
Subtree here means all the widget tree below that widget (including that widget as root node).
When we call setState function, the build method is called on the root node of the subtree, which triggers the build methods on its child. Say a branch (here MyWidget1) of a subtree (a child of that widget) is independent of the state variables. I noticed that even independent branches are rebuilt on setState called in the parent node.
class _MyAppState extends State<MyApp> {
int count=0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[ MyWidget1(),MyWidget2(count),],),
floatingActionButton: FloatingActionButton(onPressed: ()=>setState((){count++;}),),
);
}
}
class MyWidget1 extends StatelessWidget {
#override
Widget build(BuildContext context) { print("widget builds 1");
return Container(height: 100, color: Colors.orange,);
}
}
class MyWidget2 extends StatelessWidget {
final int count;
MyWidget2(this.count);
#override
Widget build(BuildContext context) { print("widget builds 2");
return Text(count.toString());
}
}
Here we can see that MyWidget1 is independent of the state variable (here count), so generally, setState should have no impact on it.
I was wondering if there should be any optimization to avoid that useless build of MyWidget1 on the call of setState function. As the tree below MyWidget1 can be too big, that too will be rebuild again.
My Questions:
Is it Ok for this Independent Widget (here MyWidget1) to build again on setState?
Is there a better way to deal with this situation to avoid its rebuild.
Note: I have read this question
In this question, there is a way to avoid useless build by creating an instance of the independent branch outside the build method,
My doubt is :
Is this the WAY to deal with this situation or some other better way or this situation isn't that big at all as tree builds in O(n) time (which I think shouldn't be the answer because building tree might be O(n) operation but it may include many time-consuming operations which may not be optimization friendly to call again and again uselessly).
Yes, MyWidget1 is rebuilt upon that setState. Just trust the code. After you call setState, build is called, which calls the constructor of MyWidget1. After each setState, the entire subtree is rebuilt. Old widgets are thrown away. States are not thrown away, though. State instances live on, they are not recreated (see didUpdateWidget).
So, yes. After each setState, the entire subtree is rebuilt.
This is OK, don't worry.
The widget classes here are very lightweight classes. Dart's garbage collector is optimized to instantiate many such objects and throw them away together.
This tree that you get to recreate again and again is just a facade. There are two more parallel trees that are not lightweight and are not recreated. Your widget trees are diff'ed together to find how the actual ui elements should be modified by the system.
Why all this trouble, you may ask. Because creating trees is easy and maintaining them is difficult. This reactive declarative framework lets us get away with only creating the tree and not maintaining it.
There are some resources about Flutter internals that you can read more about this. One such resource is this video: https://www.youtube.com/watch?v=996ZgFRENMs
class _MyAppState extends State<MyApp> {
int count=0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[ const MyWidget1(),MyWidget2(count),],),
floatingActionButton: FloatingActionButton(onPressed: ()=>setState((){count++;}),),
);
}
}
class MyWidget1 extends StatelessWidget {
const MyWidget1();
#override
Widget build(BuildContext context) { print("widget builds 1");
return Container(height: 100, color: Colors.orange,);
}
}
class MyWidget2 extends StatelessWidget {
final int count;
MyWidget2(this.count);
#override
Widget build(BuildContext context) { print("widget builds 2");
return Text(count.toString());
}
}
when the constructor starts with a "const" keyword, which allows
you to cache and reuse the widget.
When calling the constructor to initiate the widget, use the "const" keyword. By calling with the "const" keyword, the widget does not rebuild when any parent widgets change
their state in the tree. If you omit the "const" keyword, the widget will be build every time the parent
widget redraws.