preface

Because of business adjustment, I began to learn Flutter and rewrote the functional App of the business line. It encountered many pits, this time mainly summarized the content of the routing stack and life cycle, and then slowly supplement ~

What is routing

What is a route, “Routes”? Routing is an abstraction of a screen or application page.

Flutter allows us to elegantly manage routes primarily by relying on the Navigator class. This is a Widget that manages a set of pages that have some sort of entry and exit rule, which means that you can switch between pages regularly. The rules are a “routing stack” maintained internally.

After routing

In general, we use named routing most often, which is to name each page that needs to be accessed by the application as a unique string that we can use to push the page instance into the route.

Such as:

new MaterialApp(
  home: new Screen1(),
  routes: <String, WidgetBuilder> {
    '/screen1': (BuildContext context) => new Screen1(),
    '/screen2' : (BuildContext context) => new Screen2(),
    '/screen3' : (BuildContext context) => new Screen3(),
    '/screen4' : (BuildContext context) => new Screen4()
  },
)
Copy the code

Routing stack

The Navigator maintains a stack to hold the state of the route jump.

Jump from screen1 to screen2

Navigator.pushNamed(context, '/screen2')
Copy the code

Exit route POP

Navigator.pop()

Do not use pushNamed instead of Pop, or the following will happen.

The life cycle

After a brief talk about the routing stack, I’ll move on to a series of life cycles for StatefulWidget.

The diagram above shows the life cycle diagram of State.

StatefulWidget.createState()

Framework by calling StatefulWidget. CreateState () to create a State.

initState()

The newly created State is associated with a BuildContext, where State is thought to be installed and initState() will be called. In general, we can rewrite this function to initialize it.

didChangeDependencies()

This function is called after initState() is called. In fact, this function is always called by the Framework when the dependency of the State object changes.

build()

After the above steps, the system decides that a State is ready and calls build() to build the view. We need to return a Widget in this function.

deactivate()

This function is called when State is temporarily removed from the view tree. It is also called when the page switches, because State’s position in the view tree changes and needs to be temporarily removed before being added. ⚠️ Note that super.deactivate() must be called when overwriting.

dispose()

The Framework calls this function when State is permanently removed from the view tree. Triggered before destruction, we can do the final resource release here. Deactivate () is always called before calling this function. ⚠️ Note that super.dispose() must be called when overwritten

didUpdateWidget(covariant T oldWidget)

This function is called when the configuration of the widget changes. For example, this function is called when hot-reload is performed. After this function is called, build() is called.

setState()

When I need to update the view of State, I need to manually call this function, which triggers build().

Usually we use most is initState, build, deactivate, dispose, setState. Next, the triggering conditions of initState and Dispose in the process of route jump are mainly discussed.

It is used when the route is redirectedinitState.deactivate.dispose

That’s what we wrote at the beginning

@override
void initState() {
    super.initState();
    print('------initstate--------');
}

void deactivate() {
    super.deactivate();
    print('-----deactivate----');
}

void dispose() {
    super.dispose();
    print('----dispose--------');
}
Copy the code

When we jump to other routes through pushNamed, we find that deactivate is triggered, but Dispose is not triggered, and return to this page through pushNamed again, initstate is not executed again.

Those of you who have written a lot of Vue single page applications know that this can be very frustrating. Many times like Vue, we need to initialize data at created time and remove some listening events or destroy timers from the page beforeDestroy to prevent memory leaks.

Let’s go back to the lifecycle specification:

Deactivate () this function is called when State is temporarily removed from the view tree.

Dispose () The Framework calls this function when State is permanently removed from the view tree.

At this time is not suddenly enlightened! PushNamed only removes views temporarily, not completely, which leads to some strange problems (if, like me, you have a business need to control page initialization and destruction)

How to do that. PopAndPushNamed now! Replace pushNamed with it, and you’ll find that all events that trigger trigger ~

popAndPushNamedThe current route is ejected and forwarded to the new route to completely remove the old route.

There are similar methods pushReplacementNamed pushNamedAndRemoveUntil etc., are not here.

Cancel the return key for navigation headers

AppBar(automaticallyImplyLeading: false)
Copy the code

WillPopScopeCancel the Android physical back key

This method also cancels the iOS default left/right swipe to switch routes.

Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          return false;
        },
        child: Scaffold(
            // Your Code
        )
    );
}
Copy the code