I am trying to understand how state and lifting state works in Flutter. In the code below I made a simple app where I tried to pass or lift a string and a function through multiple levels.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String data = 'MyApp class data';
void setTextField(String s) {
setState(
() {
data = s;
},
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainApp(data, setTextField),
);
}
}
class MainApp extends StatelessWidget {
final String mainAppData;
final Function setTextField;
MainApp(this.mainAppData, this.setTextField);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(mainAppData)),
body: Container(
child: Level2(mainAppData, setTextField),
),
);
}
}
class Level2 extends StatelessWidget {
final String level2Data;
final Function setTextField;
Level2(this.level2Data, this.setTextField);
@override
Widget build(BuildContext context) {
return Container(
child: Level3(level2Data, setTextField),
);
}
}
class Level3 extends StatefulWidget {
final String level3Data;
final Function setTextField;
Level3(this.level3Data, this.setTextField);
@override
_Level3State createState() {
print('Level3: $this.level3Data');
return _Level3State(this.level3Data, this.setTextField);
}
}
class _Level3State extends State<Level3> {
String level3Data;
Function setTextField;
_Level3State(this.level3Data, this.setTextField);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
onChanged: setTextField,
),
Text(level3Data),
],
);
}
}
When the app starts, the string data in the _MyAppState state class is passed to the MainApp StatelessWidget when MainApp is built. In a similar manner, info is passed then to Level2 StatelessWidget and Level3 StatefulWidget.
When the TextField in Level3 changes, setTextField is triggered. setTextField is defined up in MyApp and I figured that when the String data changes (inside setState()) it should trigger rebuilding of all the widgets affected by the change.
The text in the MainApp widget (appBar) changes, showing MainApp was rebuilt as I expected. But nothing happens to the Level3 widget; it's not rebuilt. The print statement in the createState() method does not execute, and the Text widget's text does not change.
Why doesn't the Level3 StatefulWidget rebuild?