Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MaterialPageRoute builder is called three times during route lifecycle #14124

Closed
lukef opened this issue Jan 16, 2018 · 10 comments
Closed

MaterialPageRoute builder is called three times during route lifecycle #14124

lukef opened this issue Jan 16, 2018 · 10 comments
Labels
f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels.

Comments

@lukef
Copy link
Contributor

lukef commented Jan 16, 2018

It appears that builder functions for MaterialPageRoute (as well as PageRouteBuilder) is being called for the following lifecycle events:

  • Before enter
  • Entered
  • Exit (if you dismiss the route)

I'm not sure if this is normal or if you can differentiate between each of the events but it could lead to code execution issues. It may just be unclear documentation (or I totally missed something?).

Example:

new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
  print("Test message");
  return SomeWidget();
});

"Test message" will appear in the log three times.

@GRouslan
Copy link

GRouslan commented Jan 26, 2018

MaterialPageRoute builds every time I put a finger in a TextField, so the cursor runs to the starting position and I am unable to put the cursor in the middle of a text:

MaterialPageRoute:

Navigator.of(context).push(new MaterialPageRoute<Null>(
      builder: (BuildContext context) {
        return new EditPersonDialog(person);
      },
    ));

TextField:

new TextField(
                maxLines: null,
                controller: textEditingController,
                onChanged: (text) => ...)

@GRouslan
Copy link

GRouslan commented Jan 26, 2018

Dirty workaround (copy-paste works with it as well):

class MyRoot extends MaterialPageRoute<Null> {

  final Person person;

  MyRoot(this.person) : super(builder: (BuildContext context) {
    return new EditPersonDialog(person);
  },);

  @override
  Color get barrierColor => super.barrierColor;

  Widget cashed;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    if (cashed == null) {
      cashed = super.buildPage(context, animation, secondaryAnimation);
    }
    return cashed;
  }

  @override
  bool get maintainState => super.maintainState;

  @override
  Duration get transitionDuration => super.transitionDuration;
}

@Hixie
Copy link
Contributor

Hixie commented Jan 29, 2018

Build methods can get called a lot; build methods should be idempotent (that is, calling them repeatedly should have no side-effects). Why is it that rebuilding the route is clearing your text field? Are you recreating the textEditingController in the build method, maybe?

@GRouslan
Copy link

GRouslan commented Jan 30, 2018

This is my code essence, I have no idea where I bring side-effects:

import 'package:flutter/material.dart';

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

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

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(title),
      ),
      body: new Center(
        child: new FlatButton(
          onPressed: () => openDialog(context),
          child: new Text('Open dialog'),
        ),
      ),
    );
  }

  void openDialog(BuildContext context) {
    Navigator
        .of(context)
        .push(new MaterialPageRoute<Null>(builder: (BuildContext context) {
      return new MyDialog();
    }));
  }
}

class MyDialog extends StatelessWidget {
  final TextEditingController textEditingController;

  MyDialog()
      : textEditingController = new TextEditingController(text: 'initial');

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new Padding(
      padding: const EdgeInsets.all(16.0),
      child: new Center(
        child: new TextField(
          maxLines: null,
          controller: textEditingController,
        ),
      ),
    ));
  }
}

@Hixie
Copy link
Contributor

Hixie commented Feb 1, 2018

You have a stateless widget that has state (a text editing controller).

@GRouslan
Copy link

GRouslan commented Feb 1, 2018

Sorry, I have to read documentation again.

@xster xster added the f: routes Navigator, Router, and related APIs. label Mar 31, 2018
@zoechi zoechi added the framework flutter/packages/flutter repository. See also f: labels. label Jul 22, 2018
@goderbauer
Copy link
Member

As far as I can tell there's nothing actionable in this issue (as has been pointed out, build methods should be idempotent). Closing this for now, but feel free to reopen with additional information if there's more to it.

@goderbauer
Copy link
Member

See also: #11655

@hbirdGit
Copy link

hbirdGit commented Jul 5, 2020

Build methods can get called a lot; build methods should be idempotent (that is, calling them repeatedly should have no side-effects). Why is it that rebuilding the route is clearing your text field? Are you recreating the textEditingController in the build method, maybe?

"build methods should be idempotent " clear my all misunderstandings. Thank you

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 19, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

No branches or pull requests

7 participants