Pages on Navigator stack rebuild when a new page is pushed in Flutter
Solution 1
I solved the problem by simply changing the class like this :
import 'package:flutter/material.dart';
class UserLoader extends StatefulWidget {
@override
_UserLoaderState createState() => new _UserLoaderState();
}
class _UserLoaderState extends State<UserLoader> {
Widget _form; // Save the form
@override
Widget build(BuildContext context) {
if (_form == null) { // Create the form if it does not exist
_form = _createForm(context); // Build the form
}
return _form; // Show the form in the application
}
Widget _createForm(BuildContext context) {
// This is the exact content of the build method in the question
final _formKey = new GlobalKey<FormState>();
final _emailController = new TextEditingController();
return new Scaffold(
appBar: new AppBar(
title: new Text("Informations"),
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.save),
onPressed: () {
// unrelated stuff happens here
})
],
),
body: new Center(
child: new SingleChildScrollView(
child: new Form(
key: _formKey,
child: new Column(children: <Widget>[
new ListTile(
leading: const Icon(Icons.email),
title: new TextFormField(
decoration: new InputDecoration(
hintText: "Email",
),
keyboardType: TextInputType.emailAddress,
controller: _emailController,
validator: _validateEmail,
),
),
]))),
));
}
}
}
Hope this may help someone else someday.
Solution 2
All you need to do is move this row
final _formKey = new GlobalKey<FormState>();
from build
method to state class declaration (i.e. outside from build
). Key must be created once when class is created. In your case the key is re-created each build action.
Comments
-
Daneel over 1 year
I'm developing a Flutter app which prompts a form asking for some personal info.
The problem is that the page is being rebuilt every time something happens, like when the screen orientation changes or when a text field gets the focus (the keyboard appears and disappears right away, preventing the user from typing anything).
Obviously something is triggering unwanted rebuilds, but I couldn't find out what and where.
When I plug this page as the homepage, everything works fine. The issue happens when I plug the page at its intended position, after an animation is displayed on a splash screen, so I guess it has something to do with my problem.
Main class :
import 'package:flutter/material.dart'; import './view/SplashScreen.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new SplashScreen(), ); } }
Splash screen :
import 'package:flutter/material.dart'; import 'dart:async'; import './UserLoader.dart'; class SplashScreen extends StatefulWidget { @override _SplashScreenState createState() => new _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin { AnimationController _iconAnimationController; CurvedAnimation _iconAnimation; @override void initState() { super.initState(); _iconAnimationController = new AnimationController( vsync: this, duration: new Duration(milliseconds: 2000)); _iconAnimation = new CurvedAnimation( parent: _iconAnimationController, curve: Curves.easeIn); _iconAnimation.addListener(() => this.setState(() {})); _iconAnimationController.forward(); startTimeout(); } @override Widget build(BuildContext context) { return new Material( color: Colors.white, child: new InkWell( child: new Center( child: new Container( width: 275.0, height: 275.0, decoration: new BoxDecoration( image: new DecorationImage( colorFilter: new ColorFilter.mode( Colors.white.withOpacity(_iconAnimation.value), BlendMode.dstATop), image: new AssetImage("images/logo.png")), ), ), ), ), ); } void handleTimeout() { Navigator.of(context).pushReplacement(new MaterialPageRoute( builder: (BuildContext context) => new UserLoader())); } startTimeout() async { var duration = const Duration(seconds: 3); return new Timer(duration, handleTimeout); } }
Faulty page :
import 'package:flutter/material.dart'; class UserLoader extends StatefulWidget { @override _UserLoaderState createState() => new _UserLoaderState(); } class _UserLoaderState extends State<UserLoader> { @override Widget build(BuildContext context) { final _formKey = new GlobalKey<FormState>(); final _emailController = new TextEditingController(); return new Scaffold( appBar: new AppBar( title: new Text("Informations"), actions: <Widget>[ new IconButton( icon: const Icon(Icons.save), onPressed: () { // unrelated stuff happens here }) ], ), body: new Center( child: new SingleChildScrollView( child: new Form( key: _formKey, child: new Column(children: <Widget>[ new ListTile( leading: const Icon(Icons.email), title: new TextFormField( decoration: new InputDecoration( hintText: "Email", ), keyboardType: TextInputType.emailAddress, controller: _emailController, validator: _validateEmail, ), ), ]))), )); }}
Can anybody help me find out why the page is continuously rebuilding itself ?
-
Nato Boram over 5 yearsYou should probably note the changes you did to the class so other people won't have to look trough the code to find an answer.
-
Daneel over 5 years@NatoBoram You're right, I added some comments in the code to highlight the changes :)
-
Sibin over 5 years@Daneel What happens if I need to do error handling in this screen? Like email validation.
-
Daneel over 5 years@Sibin Sorry, this project is a bit old for me, but as I recall, my
_validateEmail
returnednull
if the email was correct, or a message error (a simple string) which was displayed automatically underneath the field. The Save button had a method calling something like_formKey.currentState.validate()
to check if everything was alright - if the email was wrong, the validator returned false and prevented the "save" action. Flutter handled it all nicely. Hope this helps, otherwise you can post a question on SO to get better answers. -
Sibin about 5 years@Daneel Thanks for the reply. In my project implemented streambuilder then everything is working perfectly now .
-
putulputul about 5 yearsDear, You save my life and save my time. Please take my heartiest thanks
-
emowise over 4 yearsChecking _form==null saved my hours. Thanks)
-
Gyuri Majercsik about 4 yearsI wouldn't recommend this. Hot reload stops working if you cache the widget.
-
ff .n about 3 yearsI had this problem for a few days and I was looking for a solution, but my problem still persisted But your solution helped a lot,thanks a lot