Reputation: 452
I am very new to flutter and the millions of answers I have read online made me even more confusion. This is my page:
class SecondDegreePage extends StatefulWidget {
const SecondDegreePage({Key key}) : super(key: key);
@override
SecondDegreePageState createState() => SecondDegreePageState();
}
class SecondDegreePageState extends State<SecondDegreePage> {
final GlobalKey<FormState> _formKey = new GlobalKey();
final controllerParamA = TextEditingController();
final controllerParamB = TextEditingController();
final controllerParamC = TextEditingController();
Quadratic _solver = Quadratic([
(Random().nextInt(10) + 1) * 1.0,
(Random().nextInt(10) + 1) * 1.0,
(Random().nextInt(10) + 1) * 1.0
]);
void updateData() {
setState(() {
_solver = Quadratic([
(Random().nextInt(10) + 1) * 1.0,
(Random().nextInt(10) + 1) * 1.0,
(Random().nextInt(10) + 1) * 1.0
]);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalization.of(context).title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
// Input form
Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
EquationInputField(
controller: controllerParamA,
textHint: 'a',
width: 70,
),
EquationInputField(
controller: controllerParamB,
textHint: 'b',
width: 70,
),
EquationInputField(
controller: controllerParamC,
textHint: 'c',
width: 70,
),
],
),
),
),
// Submit button
Padding(
padding: EdgeInsets.fromLTRB(0, 30, 0, 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () => updateData(),
color: Colors.blue,
elevation: 6,
child: Text(
AppLocalization.of(context).solve,
style: TextStyle(
color: Colors.white
),
),
)
],
),
),
//Solutions
Expanded(
child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: AlgebraicSolutions(
solver: _solver
),
),
),
],
),
);
}
@override
void dispose() {
controllerParamA.dispose();
controllerParamB.dispose();
controllerParamC.dispose();
super.dispose();
}
}
The type Quadratic is simply a class that does some math, nothing important. The problem is in this line:
RaisedButton(
onPressed: () => updateData()
}
Why nothing happens? I have read thet the call to setState calld the build method and the widget is re-built. For this reason I expect that
child: AlgebraicSolutions(
solver: _solver
),
here the _solver
reference gets updated. AlgebraicSolutions is the following:
class AlgebraicSolutions extends StatefulWidget {
final Algebraic solver;
const AlgebraicSolutions({Key key, @required this.solver}) : super(key: key);
@override
AlgebraicSolutionsState createState() => AlgebraicSolutionsState();
}
class AlgebraicSolutionsState extends State<AlgebraicSolutions> {
//'Quadratic' is a subtype of Algebraic
Algebraic _solver;
@override
void initState() {
_solver = widget.solver;
super.initState();
}
@override
Widget build(BuildContext context) {
var solutions = _solver.solve();
return ListView.builder(
itemCount: solutions.length,
itemBuilder: (context, index) {
//...
}
);
}
}
Is that because I am using initState
in AlgebraicSolutionsState that breaks something?
Please note that Quadratic type is subclass of Algebraic type.
Upvotes: 1
Views: 1402
Reputation: 3506
Yep, saving the initial value in initState
is what's giving you trouble. That lifecycle method is only called on first build but since the widget reconciles to the compatible type the same state is used. i.e. the properties change (widget instance is different) but the state is the same object. build
gets called again but initState
does not.
In this situation I would use a getter to give you the same convenience but always use the _solver
from the current widget
. Then you can discard the initState
.
Algebraic get _solver => widget.solver;
The other option being didUpdateWidget
but it really not necessary here for something so straightforward otherwise.
Upvotes: 4