MOCKSTACKS
EN
Questions And Answers

More Tutorials









Flutter State and Stateful Widget Approach

Approach

Store state in Stateful Widgets at a high-enough level in the Widget tree to ensure that the data is not repeated.
Pass state from parent Widgets to child Widgets through the constructor.
Pass event handler method (that modifies state) from parent Widget methods to child Widgets through the constructor. Child Widgets can then invoke method to change state in Parent Widget.
Exercise – ‘state_and_stateful_widget’

Introduction

We start off by creating a create basic app with Stateful and Stateless Widgets.
Later on, we add some state & event handling so that the user can select a car and see it highlighted.
The car selection comes from a tap event in the lower-level CarWidget.
It changes the selected car state in the higher-level MyHomePageWidget.
Step 1 – Create Default Flutter App
Follow the instructions in Generate Your First App Leave project open.
Step 2 – Replace Application Code
Replace contents of file ‘main.dart’ in folder ‘lib’ with the following:

importpackage:flutter/material.dart’;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: ‘Flutter Demo’,
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class Car {
String _make;
String _model;
String _imageSrc;
Car(this._make, this._model, this._imageSrc);
operator ==(other) =>
(other is Car) && (_make == other._make) && (_model == other._model);
int get hashCode => _make.hashCode ^ _model.hashCode ^ _imageSrc.hashCode;
}
class MyHomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState(“Cars”);
}
class _HomePageState extends State<MyHomePage> {
String _title;
List<Car> _cars;
_HomePageState(this._title) {
_cars = [
Car(
“Bmw”,
“M3”,
“Https://media.ed.edmundsmedia.com/bmw/m3/2018/oem/2018_bmw_m3_sedan_base_fq_oem_4_150.jpg
Https://media.ed.edmundsmedia.com/bmw/m3/2018/oem/2018_bmw_m3_sedan_base_fq_oem_4_150.jpg
“,
),
Car(
“Nissan”,
“GTR”,
“Https://media.ed.edmunds-media.com/nissan/gt-r/2018/oem/2018_nissan_gtr_coupe_nismo_fq_oem_1_150.jpg
Https://media.ed.edmunds-media.com/nissan/gt-r/2018/oem/2018_nissan_gtr_coupe_nismo_fq_oem_1_150.jpg
”,
),
Car(
“Nissan”,
“Sentra”,
“Https://media.ed.edmundsmedia.com/nissan/sentra/2017/oem/2017_nissan_sentra_sedan_srturbo_fq_oem_4_150.jpg
Https://media.ed.edmundsmedia.com/nissan/sentra/2017/oem/2017_nissan_sentra_sedan_srturbo_fq_oem_4_150.jpg
”,
)
];
}
@override
Widget build(BuildContext context) {
List<CarWidget> carWidgets = _cars.map((Car car) {
return CarWidget(car);
}).toList();
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
body: new ListView(children: carWidgets));
}
}
class CarWidget extends StatelessWidget {
CarWidget(this._car) : super();
final Car _car;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(20.0),
child: Container(
decoration: BoxDecoration(border: Border.all()),
padding: EdgeInsets.all(20.0),
child: Center(
child: Column(children: <Widget>[
Text(‘${_car._make} ${_car._model}’,
style: TextStyle(fontSize: 24.0)),
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Image.network(_car._imageSrc))
]))));
}
}

Step 3 – Open Emulator & Run
Follow the instructions in Open Android Emulator & Run Your First App You should get something like the following as it is somewhat similar to the previous example:

Summary


The MyApp & Material App Widgets are unchanged. We declare a new class called Car.
This will store information about each car: its make, model and image.
Note that the ‘==’ operator is overloaded so it considers two Cars equal if they have the same make and model.
The MyHomePage Stateless Widget has become two different widgets instead:

MyHomePage StatefulWidget


MyHomePageState State Object
This holds the App Bar title and the list of Car objects.
These are initiated in the constructor.
The State object contains the ‘build’ method that converts the list of Car objects into a list of CarWidgets.
Then it returns a Scaffold containing the AppBar and a ListView containing the list of CarWidgets.

CarWidget


This displays a car’s make, model and image.
Notice that it now accepts a Car object in the constructor. This gives it all the info to display a car’s make, model and image.
Step 4– Add Car Selection
This is going to be achieved by holding state in the MyHomePage state object.
This state is going to be set by a method. This method is going to be passed to each Car Widget so it can be invoked by the Car Widget
when the user taps on it.

Modify MyHomePageState

We add variable ‘_selectedCar’ to store which car is selected. We add a method ‘_selectionHandler’ to handle car selection.
This provides an inline JavaScript function that sets the variables ‘_title’ and ‘_selectedCar’.
This inline JavaScript function is passed to setState. Using ‘setState’ tells Flutter that the state of this object has changed and that this Widget will need to be re- endered. We change the code that constructs the CarWidgets to include 2 additional constructor arguments:
A boolean indicating if the car is the selected car.
The selection handler method that handles the car selection in this class.

class MyHomePageState extends State<MyHomePage> {
String _title;
List<Car> _cars;
Car _selectedCar;
MyHomePageState(this._title) {
_cars = [
Car(
“Bmw”,
“M3",
“Https://media.ed.edmundsmedia.com/bmw/m3/2018/oem/2018_bmw_m3_sedan_base_fq_oem_4_150.jpg“,
),
Car(
“Nissan”,
“GTR”,
“Https://media.ed.edmunds-media.com/nissan/gt-r/2018/oem/2018_nissan_gtr_coupe_nismo_fq_oem_1_150.jpg”,
),
Car(
“Nissan”,
“Sentra”,
“Https://media.ed.edmundsmedia.com/nissan/sentra/2017/oem/2017_nissan_sentra_sedan_srturbo_fq_oem_4_150.jpg”,
)
];
}
void _selectionHandler(Car selectedCar) {
setState(() {
_title = ‘Selected ${selectedCar._make} ${selectedCar._model}’;
_selectedCar = selectedCar;
});
}
@override
Widget build(BuildContext context) {
List<CarWidget> carWidgets = _cars.map((Car car) {
return CarWidget(car, car == _selectedCar, _selectionHandler);
}).toList();
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
body: new ListView(children: carWidgets));
}
}
Modify CarWidget
We add instance variable ‘_isSelected’ to store if this car is selected
or not. We add instance variable ‘_parentSelectionHandler’ to store the
selection handler method from the parent MyHomePageState class. We modify the constructor to accept & set these two instance
variables. We add a new method ‘_handleTap’ to handle the ‘onTap’ event
from the GestureDetector. This method invokes the
‘_parentSelectionHandler’ from the parent MyHomePageState
class. We modify the ‘build’ method. We wrap the Container with a GestureDetector. This is so we
can listen for the ‘onTap’ event. We modify the ‘BoxDecoration’ to set the background color
according to if the instance variable ‘isSelected’ is set to true
or false. If true the background color is set to blue, otherwise
white.
class CarWidget extends StatelessWidget {
CarWidget(this._car, this._isSelected, this._parentSelectionHandler)
: super();
final Car _car;
final bool _isSelected;
final ValueChanged<Car> _parentSelectionHandler;
void _handleTap() {
_parentSelectionHandler(_car);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(20.0),
child: GestureDetector(
onTap: _handleTap,
child: Container(
decoration: BoxDecoration(
color: _isSelected ? Colors.blue : Colors.white,
border: Border.all()),
padding: EdgeInsets.all(20.0),
child: Center(
child: Column(children: <Widget>[
Text(‘${_car._make} ${_car._model},
style: TextStyle(fontSize: 24.0)),
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Image.network(_car._imageSrc))
])))));
}
}



Conclusion

In this page (written and validated by ) you learned about Flutter State and Stateful Widget Approach . What's Next? If you are interested in completing Flutter tutorial, your next topic will be learning about: Flutter State and Inherited Widget Approach.



Incorrect info or code snippet? We take very seriously the accuracy of the information provided on our website. We also make sure to test all snippets and examples provided for each section. If you find any incorrect information, please send us an email about the issue: mockstacks@gmail.com.


Share On:


Mockstacks was launched to help beginners learn programming languages; the site is optimized with no Ads as, Ads might slow down the performance. We also don't track any personal information; we also don't collect any kind of data unless the user provided us a corrected information. Almost all examples have been tested. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. By using Mockstacks.com, you agree to have read and accepted our terms of use, cookies and privacy policy.