I have StatefulWidget instance.
However I want to access the method of State from the instance of StatefulWidget.
It might be very simple and basic for flutter, but for the beginner of Stateful/State systen, it is a bit complex.
class MainBody extends StatefulWidget{
#override
_MainBodyState createState() => _MainBodyState();
}
class _MainBodyState extends State<MainBody>{
_MainBodyState();
void connectMainBody(){
print("ConnectMainBody");
}
class _MyHomePageState extends State<MyHomePage> {
Widget mainBody;
#override
void initState() {
super.initState();
mainBody = new MainBody();
mainBody.connectMainBody()// how can I access this method??
}
My idea was completely wrong.
https://medium.com/flutter-community/flutter-communication-between-widgets-f5590230df1e
I checked this page and learned.
How to access from Parent to Child.
By giving parameters to Child's Constructor.
How to access from Child to Parent.
By using callback function given to Child from Parent in advance.
I think I should learn about GlobalKey next.
Thank you very much for your advice.
Related
a variable is a final variable from a different page, Widget is Stateful, and I want to access it in initstate.
I can't use it directly or can access using another variable.
If the variable is final and defined on a different page, you won't be able to directly access it in the initState method of a Stateful widget. However, you may be able to access it indirectly by passing it as a parameter to the Stateful widget's constructor.
For example, you could define a constructor for your Stateful widget that takes the final variable as a parameter and then store that variable in the widget's state:
class MyWidget extends StatefulWidget {
final String myFinalVariable;
MyWidget({required this.myFinalVariable});
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String? myVariable;
#override
void initState() {
super.initState();
myVariable = widget.myFinalVariable;
}
// rest of your widget code...
}
createState:
Creates the mutable state for this widget at a given location in the tree.
https://api.flutter.dev/flutter/widgets/StatefulWidget/createState.html
Now, in code:
class A extends StatefulWidget {
#override
_AState createState() => _AState();
}
class _AState extends State<A> {
}
Here we create a separate class named _AState which inherits from a predefined class named State?
So, what is createState' role here? How does it create a mutable state for us?
With createState you tell the StatefulWidget which class to use as state for this widget. And you tell it here that it needs to create an instance of _AState for this widget.
By the way, it is also recommended to write it as
State<A> createState() => _AState();
It still works the way you wrote it but the IDE might complain about
Avoid using private types in public APIs
Saying the return type is State<A> instead of _AState removes this warning.
In order to create a stateful widget in a flutter, it uses the createState() method. Stateful Widget means a widget that has a mutable state.
I want to have a StatefulWidget where I can pass the initial value for a non-nullable member of the widgets State from the widgets constructor.
My current solution (see below) seems to be not ideal, I see two problems with it:
The initial value has to be saved in the widget itself before passing it to the state.
The member in the sate has to be marked as late since it can only be set after initialization.
Is there a better way to initialize a StatefulWidget's state non-nullable member from a value passed to the widget constructor?
My current implementation:
class MyWidget extends StatefulWidget {
final String text;
const MyWidget({Key? key, required this.text}) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late String text;
#override
void initState() {
text = widget.text;
super.initState();
}
#override
Widget build(BuildContext context) {
return Text(text);
}
}
(Not shown here, but later the text member should be changeable, that's why it is in the State)
hey there your code seems good.
but the better way is using bloc to pass and receive data.
any way . its not necessary to pass and fill data in initstate and _MyWidgetState .
you can receive your data directly in build widget As you wrote (widget.text)
here is some good things for avoid nullable
https://codewithandrea.com/videos/dart-null-safety-ultimate-guide-non-nullable-types/
You could use the constructor of State like this: _MyWidgetState(){ text=widget.text; }. The constructor will certainly be executed before initState and build methods.
I'm currently learning Flutter. I tried to deep dive into Flutter Widget life-cycle, and I wonder why StatefulWidget are written like this :
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
// initState
// setState
// ...
#override
Widget build(BuildContext build) {
...
}
}
but not :
class Example extends StatefulWidget {
// initState
// setState
// ...
#override
Widget build(BuildContext build) {
...
}
}
I think the latter makes the source simple. But I don't know why they're using the former style ?
The reason why StatefulWidget uses a separate State class and not having build method inside its body is because all fields inside a Widget are immutable, and this includes all its sub-classes.
You might have noticed that StatelessWidget has its build and other associated methods defined inside it, but that was possible due to the nature of StatelessWidget which is rendered completely using the provided info, and doesn't expect any future change in its State.
In the case of StatefulWidget, State information occasionally change (or expected to change) during the course of the app, thus this information isn't suitable for storage in a final field (build) to satisfy Widget class conditions (all fields are immutable). That's why State class is introduced. You just have to override the createState function to attach your defined State to your StatefulWidget, and let all that change happens in a separate class.
I'm using an InheritedWidget to expose a bloc class to child components. However, every time the widget tree gets recreated, a new instance of the bloc class is instantiated. As I'm using BehaviourSubject classes to store the latest values of some textfields, I'm loosing the current values with every recreation. How could this be solved, i.e. the bloc class should only be instantiated once.
It depends on how your provider were made, if it's an a extension of StatefulWidget with an a InheritedWidget.
If it's only extends from a InheritedWigdet, you'll miss the dispose method because it doesn't extends from StatefulBuilder, but, will never instantiate again, and the dispose method will be when you'll close your application. Check this example:
class Provider extends InheritedWidget {
Provider({Key key, Widget child}) : super(key: key, child: child);
final AppBloc bloc = AppBloc();
static AppBloc of(BuildContext context) =>
(context.inheritFromWidgetOfExactType(Provider) as Provider).bloc;
#override
bool updateShouldNotify(Provider oldWidget) => true;
}
This AppBloc is a component that has all my applcation's blocs.
But, if your provider extends an a StatefulWidget with a InheritedWidget, you can pass your bloc as a constructor parameter in the class you want, and this class should be Stateful too, so you can pass in the initState and will be rebuilted only when you access it again.
If you are using a StatefulWidget then you can instantiate the bloc in the initState method.