Differentiate between didChangeDependencies and initState?
There are a few questions that come if we are going to differentiate between them.
- Why we can’t call our context in
initState
but there is no problem fordidChangeDependencies
? - Why we have access to a context outside
build
method ( because there we have build(BuildContext context)?
Let's dive deep inside there usage and difference
initState()
Called when new Widget is inserted into the tree. The framework will call this method exactly once for each [State] object it creates. This will be called once so perform work which required to be performed only once, but remember context
can't be used here, as the widget state gets loaded only initState()
work is done.
Syntax:
@override
void initState() {
debugPrint('initState()');
super.initState();
}
didChangeDependencies()
Called when a dependency of this [State] object changes.
So, exactly How it gets called? as by the above definition, it looks like it will be called after state changes but how we come to know the state is changed?
Example:
The below example uses the Provider
state management mechanism to update the child widget from the parent widget. The Provider
has an attribute called updateShouldNotify
which decides whether to state is changed or not. If it's returning true
then only didChangeDependencies
gets called in ChildWidget
class.
updateShouldNotify is returning true by default internally, as it knows the state got changed.
Why do we need updateShouldNotify?
It’s needed because if someone wants to update the state on a specific condition. Eg: if UI required to show only even
values then we can add a condition like
updateShouldNotify: (oldValue, newValue) => newValue % 2 == 0,
Code Snippet:
class ParentWidget extends StatefulWidget {
ParentWidget({Key key, this.title}) : super(key: key); final String title; @override
_ParentWidgetState createState() => _ParentWidgetState();
}class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0; void _incrementCounter() {
setState(() {
_counter++;
});
} @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Life Cycle'),
),
body: Provider.value(
value: _counter,
updateShouldNotify: (oldValue, newValue) => true,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Press Fab button to increase counter:',
),
ChildWidget()
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}class ChildWidget extends StatefulWidget {
@override
_ChildWidgetState createState() => _ChildWidgetState();
}class _ChildWidgetState extends State<ChildWidget> {
int _counter = 0; @override
void initState() {
print('initState(), counter = $_counter');
super.initState();
} @override
void didChangeDependencies() {
_counter = Provider.of<int>(context);
print('didChangeDependencies(), counter = $_counter');
super.didChangeDependencies();
} @override
Widget build(BuildContext context) {
print('build(), counter = $_counter');
return Text(
'$_counter',
);
}
}
Output Logs:
I/flutter ( 3779): didChangeDependencies(), counter = 1
I/flutter ( 3779): build(), counter = 1