Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextField click rebuilds/reloads widget after routed

I am having an issue where the whole screen widget reloads when there is a textfield is used. This doesn't happen when the the app is loaded with this screen as landing page.

But when the routing happens from another page to this page and when textfield is clicked then the rebuild happens.

I even tried a simple app and this is getting reproduced. Tried many ways but could not get to a solution.

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';


class Screen1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Screen 1"), // screen title
      ),
      body: new Center(
        child: new Column(
          children: <Widget>[
            new RaisedButton(
              onPressed: () {
                button1(context);
              },
              child: new Text("Go to Screen 2"),
            )
          ],
        ),
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Widget rebuilds");
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Screen 2"),
      ),
      body: new Center(
        child: new Column(
          children: <Widget>[
            new Container(
                height: 350.0,
                child: TextFormField(
                  keyboardType: TextInputType.text,
                  style: TextStyle(fontSize: 16.0, color: Colors.black),
                )),

          ],
        ),
      ),
    );
  }
}

void main() {
  runApp(new MaterialApp(
    home: new Screen1(),
    routes: <String, WidgetBuilder>{
      '/screen2': (BuildContext context) => new Screen2()
    },
  ));
}

void button1(BuildContext context) {
  print("Button 1");
  Navigator.of(context).pushNamed('/screen2');
}

Here the app is loaded with screen 1 and clicking on button Go to screen2 will load the screen 2 with the text field. Clicking on this field will bring the keyboard and clicking the done on keyboard and again focusing on the text field will rebuild the screen. This keeps happening when keyboard appears and when disappears.

But then if Screen2 is set as landing page, then clicking on the text field and doing the same process mentioned above will not reload the widget. The widget build happens only once. Seems the issue is when the Screen2 is navigated from Screen 1

 runApp(new MaterialApp(
    home: new Screen2(),
    routes: <String, WidgetBuilder>{
      '/screen2': (BuildContext context) => new Screen2()
    },
  ));
like image 861
rahulmr Avatar asked Nov 22 '18 08:11

rahulmr


1 Answers

This is the normal behavior, there is no problem with it. It is in fact within the specs of build method : It can be called an arbitrary number of time and you should expect it to be so.

If this causes a problem to do so, it is very likely that your build function is not pure. Meaning that it contains side effects such as http calls or similar.

These should not be done within the build method. More details here : How to deal with unwanted widget build?


About the "What triggers the build", there are a few common situations:

  • Route pop/push, for in/out animations
  • Screen resize, usually due to keyboard appearance or orientation change
  • Parent widget recreated its child
  • An InheritedWidget the widget depends on (Class.of(context) pattern) change
like image 166
Rémi Rousselet Avatar answered Oct 15 '22 09:10

Rémi Rousselet