Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build() doesn't run again when returning to a page using the appbar back button, Flutter

Tags:

flutter

dart

I'm trying to get the app below to print Build on the return to the main page from one of the other pages.

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(
  initialRoute: '/Home',
  routes: {
    '/Home': (context) => Home(),
    '/First': (context) => First(),
    '/Second': (context) => Second(),
  },
),);


class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  void initState() {
    super.initState();
    print('Initialisation');
  }
  @override
  Widget build(BuildContext context) {
    print('Build');
    return Scaffold(
      appBar: AppBar(title: Text('Homepage')),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/First');
          },
          child: Text('Move to the first page'),
        ),
      ),
    );
  }
}

class First extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First')),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pushNamedAndRemoveUntil(context, '/Second', ModalRoute.withName('/Home'));
          },
          child: Text('Move to the second page'),
        ),
      ),
    );
  }
}

class Second extends StatefulWidget {
  @override
  _SecondState createState() => _SecondState();
}

class _SecondState extends State<Second> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second')),
    );
  }
}

Right now I am considering that maybe the leading aspect of the AppBar() widget can be edited such that this can happen but I'm really not sure. I would be very grateful for your time and any suggestions that you might have.

like image 980
Oliver Nicholls Avatar asked Dec 10 '25 23:12

Oliver Nicholls


1 Answers

This is by design - when you create a 'page', and the push another page on top of it, and then pop the new page, you want the page underneath to have the same state as before but handle the result of the pop.

To do so, you can await the result of the call to Navigator.pushNamed.

That'd look something like this:

onPressed:: () async {
  final result = await Navigator.pushNamed(context, '/First');
  // this will be after popping back to this page
  print("pop result: $result");
}

One thing to be aware of is that in the part of onPressed after the pop, your code may be running during a build cycle, so you'll want to make sure that if you call setState or Navigator.push or anything like it, you do it after having deferred that first run.

You can do that either by waiting on a delayed future or using the Scheduler

... 
await Future.delayed(Duration.zero);
(your code here)

Or,

SchedulerBinding.instance.addPostFrameCallback((duration) => (your code here))
like image 127
rmtmckenzie Avatar answered Dec 13 '25 18:12

rmtmckenzie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!