Flutter access State<T> from it's StatefulWidget - flutter

I'm writing a Application, where Widgets and their State need to be saved to Disk and later be restored. In order to save a StatefulWidget I need to access it's corresponding State<T> object.
Here's how I imagined the code to look like:
class Block extends StatefulWidget {
const Block({Key? key}) : super(key: key);
void saveToDisk(){
// access BlockState object
// save to disk…
}
#override
BlockState createState() => BlockState();
}
class BlockState extends State<Block> {
final String _someState = ‚Hello Stackoverflow‘;
#override
Widget build(BuildContext context) {
return const Text(‚Some Text‘);
}
}
Does anybody know how to access the BlockState object (first comment in saveToDisk())?

widget.saveToDisk();
All stateful widgets have it this way.

Related

What aspects to consider when defining attributes or methods in a stateful widget?

Below is the definition of a Stateful Widget and its associated state. As we can see, color has been defined in YellowBird and can be accessed in _YellowBirdState via the widget object.
My question is with respect to this, how do we decide where (Widget class or State class) to define the attributes? For example, color could have been defined in _YellowBirdState directly. For now, I am deciding this based on whether I have to access the attributes from outside. For example, considering the example below, if I need to access the attribute color from outside, then I define it in the Widget class.
class YellowBird extends StatefulWidget {
const YellowBird({ Key? key }) : super(key: key);
var color = 0xFFFFE306;
#override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
#override
Widget build(BuildContext context) {
return Container(color: Color(widget.color));
}
}
One reason to create the attributes in the widget class is to pass values from outside. In your example you could pass the color dynamically.
class YellowBird extends StatefulWidget {
Color color;
YellowBird(this.color, {Key? key}) : super(key: key);
#override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
#override
Widget build(BuildContext context) {
return Container(color: widget.color);
}
}
Now you can create your widget with different colors
YellowBird(Colors.green)
YellowBird(Colors.red)

How to make a screen that show a specific page if there's data to display and show a specific page if there's no data to display

I made 3 dart file that called Cart, CartSection, and EmptyCartState.
here is the code from Cart
class CartPage extends StatefulWidget {
const CartPage({Key? key}) : super(key: key);
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
#override
Widget build(BuildContext context) {
return Scaffold();
}
}
it's still empty.
what I want to know is how to make this Cart show CartSection if there are something in the cart and show EmptyCartState if there is nothin in the cart?
While you like to get empty screen, you can use nullable data. I am using int as datatype, you can use your model in this case.
class CartPage extends StatefulWidget {
const CartPage({
Key? key,
this.data,
}) : super(key: key);
final int? data;
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
#override
Widget build(BuildContext context) {
return widget.data == null
? Text("empty data widget")
: Text("cart data widget");
}
}
Visit dart.dev to learn more about it.

Flutter State<WidgetName> createState() => WidgetNameState()

In Flutter, when initializing a new stateful widget, it is being initialized like this by default:
class WidgetName extends StatefulWidget {
const WidgetName({ Key? key }) : super(key: key);
#override
WidgetNameState createState() => WidgetNameState();
}
I have seen another way of initializing the statefulwidget with #override being slightly different.
class WidgetName extends StatefulWidget {
const WidgetName({ Key? key }) : super(key: key);
#override
State<WidgetName> createState() => WidgetNameState();
}
Notice in the #override method, WidgetNameState became State<WidgetName>. There is an explanation in the Flutter repo that explains it: Link, but I couldn't comprehend what it is trying to say.
What does State<WidgetName> do exactly? Does it give any advantages?
I thought it wouldn't be necessary as WidgetNameState already extends from State<WidgetName> in its class construction.
class WidgetNameState extends State<WidgetName> {
#override
Widget build(BuildContext context) {
Using the generic really let's you define an abstract Widget interface that must be used without having to define any state along with that abstract widget interface.
Let's look at using the concrete class first (WidgetNameState). This is an abstract definition, we must define the state if we do this.
abstract class FooWidget extends StatefulWidget {
const FooWidget({Key? key}) : super(key: key);
#override
_FooWidgetState createState();
}
abstract class _FooWidgetState extends State<FooWidget> {
#override
Widget build(BuildContext context) {
return Container();
}
}
Now to be able to extend this you must extend both the widget and the state.
class ImplementedFooWidget extends FooWidget {
const ImplementedFooWidget({Key? key}) : super(key: key);
#override
_ImplementedFooWidgetState createState() => _ImplementedFooWidgetState();
}
class _ImplementedFooWidgetState extends _FooWidgetState {
#override
Widget build(BuildContext context) {
return Container();
}
}
Now let's look at using the generic (State<WidgetName>). If we use the generic, we can just define and extend the widget and have our own custom state.
abstract class BarWidget extends StatefulWidget {
const BarWidget({Key? key, required this.someRequiredString})
: super(key: key);
final String someRequiredString;
#override
State<BarWidget> createState();
}
class ImplementedBarWidget extends BarWidget {
const ImplementedBarWidget({Key? key, required String someRequiredString})
: super(
key: key,
someRequiredString: someRequiredString,
);
#override
_ImplementedBarWidgetState createState() => _ImplementedBarWidgetState();
}
class _ImplementedBarWidgetState extends State<ImplementedBarWidget> {
#override
Widget build(BuildContext context) {
return Container();
}
}
I hope that all makes sense.

Flutter what's StatefulHookWidget and how can we use it?

There quote is from Riverpod documentation:
A StatefulWidget that can use Hook
It's usage is very similar to StatefulWidget, but use hooks inside
State.build.
The difference is that it can use Hook, which allows HookWidget to
store mutable data without implementing a State.
besides this, I can't find any sample code or another tutorial or any description more than the quote.
in this simple HookWidget how can I implement that with StatefulHookWidget?
class MyHomePage extends HookWidget {
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
A StatefulHookWidget is for when you need to use any of the overridable functions of a regular StatefulWidget - like didChangeDependencies, or initState, or dispose.
Generally, unless you have a really good or niche reason to use StatefulHookWidget, do prefer HookWidget.
Essentially, if we replicate your example, both Class1 and Class2 are equivalent in terms of the end product. The only difference is the verbiage needed to get there.
class Class1 extends HookWidget {
const Class1({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
class Class2 extends StatefulHookWidget {
const Class2({Key? key}) : super(key: key);
#override
_Class2State createState() => _Class2State();
}
class _Class2State extends State<Class2> {
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
I am on the latest version of riverpod so I am using StatefulHookConsumerWidget
Following is one way to implement StatefulHookConsumerWidget. This might give you a hint for your answer
class MyHomePage extends StatefulHookConsumerWidget {
#override
_MyHomePage State createState() => _SocietyHomeState();
}
class MyHomePage extends ConsumerState<SocietyHome> {
Widget build(BuildContext context) {
return Container();
}
}

How to receive a parameter and use in initState within a stateful widget

I have a stateful widget that has one method called in initialisation. I wanna know how to be able to get a parameter from the previous screen and pass it in initState to my initialisation method
class LabDetalheWidget extends StatefulWidget {
final String path;
const LabDetalheWidget({
Key key,
this.path,
}) : super(key: key);
You can pass parameter like that
class MyWidget extends StatefulWidget {
final String param;
const MyWidget({
Key key,
this.param,
}) : super(key: key);
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
void initState() {
print(widget.param);
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
);
}
}
Inside the state you can access the parameter like that
print(widget.param)
I believe you wanna pass data across routes.. If so then read this flutter cookbook's section you might get the idea
https://flutter.dev/docs/cookbook/navigation/passing-data