2

I want to use MediaQuery to create responsive app. Flutter will force the page to rebuild if the keyboard popup. It makes sense. But the problem is flutter will rebuild the page even the page is deactivated.

when I routed to PageA => PageB => PageC and clicked TextField to popup the Keyboard, it will also print PageA and PageB

https://streamable.com/rogth7

Here is the reproducible example

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: APage(),
    );
  }
}

class APage extends StatefulWidget {
  const APage({super.key});

  @override
  State<APage> createState() => _APageState();
}

class _APageState extends State<APage> {
  @override
  Widget build(BuildContext context) {
    print('A Page');
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.green,
          ),
          ElevatedButton(
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => BPage(),
                    ));
              },
              child: Text('BPage')),
          Container(
            color: Colors.amber,
            child: TextField(),
          )
        ],
      ),
    );
  }
}

class BPage extends StatefulWidget {
  const BPage({super.key});

  @override
  State<BPage> createState() => _BPageState();
}

class _BPageState extends State<BPage> {
  @override
  Widget build(BuildContext context) {
    print('B Page');
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.red,
          ),
          ElevatedButton(
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => CPage(),
                    ));
              },
              child: Text('CPage')),
          Container(
            color: Colors.amber,
            child: TextField(),
          )
        ],
      ),
    );
  }
}

class CPage extends StatefulWidget {
  const CPage({super.key});

  @override
  State<CPage> createState() => _CPageState();
}

class _CPageState extends State<CPage> {
  @override
  Widget build(BuildContext context) {
    print('C Page');
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.blue,
          ),
          ElevatedButton(
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => APage(),
                    ));
              },
              child: Text('DPage')),
          Container(
            color: Colors.amber,
            child: TextField(),
          )
        ],
      ),
    );
  }
}

I expect only print PageA if I am in PageA

Anson NG
  • 21
  • 2
  • if you want to make responsive app then use LayoutBuilder https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html – Vikas Mar 20 '23 at 07:15
  • I have tried to use LayoutBuilder to replace MediaQuery.of(context).size.height * 0.1 with p1.maxHeight * 0.1, but flutter still rebuild deactivate pages – Anson NG Mar 20 '23 at 07:30
  • 1
    You don't really need to worry about this. Flutter engine calls the build method for many reasons and is capable of handling many rebuilds. It does not mean your inactive pages are rendered. – Peter Koltai Mar 20 '23 at 08:10
  • because my build method has many FutureBuilders to fetch data, and this issue caused me to call API many times, so I think I should call async function only in the initState method? Since it is ALWAYS a bad idea to use FutureBuilder(future: function()) to fetch data because of this issue, it will call number of times in the background. – Anson NG Mar 20 '23 at 08:46

0 Answers0