3

According to Flutter Documentation:

didUpdateWidget called whenever the widget configuration changes

But, in the following code, didUpdateWidget is called immediately after initState on the first time.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Test(),
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {

  @override
  void initState() {
    print("initState called");
    super.initState();
  }

  @override
  void didUpdateWidget(Test oldWidget) {
    print("didUpdateWidget called");
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}


// output
//
// initState called
// didUpdateWidget called

Can someone describe why this happens? and how can I compare the whole oldWidget with widget

Thank you

update
as @pskink mentioned, didUpdateWidget is not called immediately after initState, it's after the first build

Yet another question is why it is called after the first build with the following code:

    print("didUpdateWidget called");   <--
    super.didUpdateWidget(oldWidget);  <--

but if I call print after super.didUpdateWidget(oldWidget);, it works fine.

Pars
  • 4,932
  • 10
  • 50
  • 88
  • Hi. Please Copy & Paste the code in a flutter project and you see its called. – Pars Mar 08 '20 at 07:40
  • Yeah, you're right, but why after first build `didUpdateWidget` is called? there is no change in the widget! – Pars Mar 08 '20 at 07:45
  • Yeah I already know that, but In this simple example there is not a parent widget, but `didUpdateWidget` is called. – Pars Mar 08 '20 at 07:51
  • You swapped the `print` line with `super.didUpdateWidget` and it works as expected. so it means anything before `super.didUpdateWidget` will run immediately after the first build. Thank you for your time and reply – Pars Mar 08 '20 at 08:37
  • JUST call the print first in your code in dartpad.dartlang.org and you see `didUpdateWidget` method is called after the first build – Pars Mar 08 '20 at 08:48

1 Answers1

1

In my test using Flutter 2.10.1 stable version, didUpdateWidget was only called after calling setState() to update the data displayed on the Widget. This behavior matches the description mentioned on the docs where the didUpdateWidget method is called whenever the widget configuration changes. After the didUpdateWidget method was called, build will then be called.

Here's how the flow can look like after calling setState() once.

  1. initState()
  2. build()
  3. setState() called
  4. didUpdateWidget()
  5. build()

This can be replicated on this simple Flutter app.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  void initState() {
    debugPrint('State initState');
    super.initState();
  }


  @override
  void didUpdateWidget(MyHomePage oldWidget) {
    debugPrint('State didUpdateWidget');
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    debugPrint('State Widget build');
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
Omatt
  • 8,564
  • 2
  • 42
  • 144