一次推送两条路由时不会调用 RouteAware didPushNext

Bob*_*Bob 6 navigator flutter

当同时将两个路由推送到导航器并使用 RouteAware 获取有关当前状态的更新时,不会调用第一个路由的 didPopNext()。

看起来,在我订阅 RouteObserver 的地方调用 FirstWiget 的 didChangeDependency() 之前,两条路由都会调用 RouteObserver.didPush() (将调用 didPushNext)。

这是我所期望和得到的,当一个接一个地推送路线并等待小部件出现时:

I/flutter (30927): Navigator.push(FirstWidget)
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didPush FirstWidget
I/flutter (30927): build FirstWidget
I/flutter (30927): Navigator.push(SecondWidget)
I/flutter (30927): didPushNext FirstWidget
I/flutter (30927): didChangeDependencies SecondWidget
I/flutter (30927): didPush SecondWidget
I/flutter (30927): build SecondWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): build FirstWidget
Run Code Online (Sandbox Code Playgroud)

同时推动两者时:

I/flutter (30927): Navigator.push(FirstWidget)
I/flutter (30927): Navigator.push(SecondWidget)
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): didPush FirstWidget
I/flutter (30927): build FirstWidget
I/flutter (30927): didChangeDependencies SecondWidget
I/flutter (30927): didPush SecondWidget
I/flutter (30927): build SecondWidget
I/flutter (30927): didChangeDependencies FirstWidget
I/flutter (30927): build FirstWidget
Run Code Online (Sandbox Code Playgroud)

这是运行的示例:

import 'package:flutter/material.dart';

RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

void main() {
  runApp(MaterialApp(
    title: 'Navigation Test',
    home: StartWidget(),
    navigatorObservers: <NavigatorObserver>[routeObserver],
  ));
}

class StartWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Start'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            RaisedButton(
              child: Text('Open both routes'),
              onPressed: () {
                print("Navigator.push(FirstWidget)");
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => FirstWidget()),
                );
                print("Navigator.push(SecondWidget)");
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondWidget()),
                );
              },
            ),
            RaisedButton(
              child: Text('Open FirstWidget'),
              onPressed: () {
                print("Navigator.push(FirstWidget)");
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => FirstWidget()),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

class FirstWidget extends StatefulWidget {
  @override
  _FirstWidgetState createState() => _FirstWidgetState();
}

class _FirstWidgetState extends RouteAwareState<FirstWidget> {
  Widget build(BuildContext context) {
    print("build $widget");
    return Scaffold(
      appBar: AppBar(
        title: Text('FirstWidget'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            RaisedButton(
              child: Text('Open SecondWidget'),
              onPressed: () {
                print("Navigator.push(SecondWidget)");
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondWidget()),
                );
              },
            ),
            RaisedButton(
              child: Text('back'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

class SecondWidget extends StatefulWidget {
  @override
  _SecondWidgetState createState() => _SecondWidgetState();
}

class _SecondWidgetState extends RouteAwareState<SecondWidget> {
  @override
  Widget build(BuildContext context) {
    print("build $widget");
    return Scaffold(
      appBar: AppBar(
        title: Text('SecondWidget'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('back'),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ),
    );
  }
}

abstract class RouteAwareState<T extends StatefulWidget> extends State<T>
    with RouteAware {
  @override
  void didChangeDependencies() {
    print("didChangeDependencies $widget");
    routeObserver.subscribe(this, ModalRoute.of(context)); //Subscribe it here
    super.didChangeDependencies();
  }

  @override
  void didPush() {
    print('didPush $widget');
  }

  @override
  void didPopNext() {
    print('didPopNext $widget');
  }

  @override
  void didPop() {
    print('didPop $widget');
  }

  @override
  void didPushNext() {
    print('didPushNext $widget');
  }

  @override
  void dispose() {
    print("dispose $widget");
    routeObserver.unsubscribe(this);
    super.dispose();
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:编辑以直接包含代码。

Bob*_*Bob 1

放置时

WidgetsBinding.instance.addPostFrameCallback()
Run Code Online (Sandbox Code Playgroud)

在两次Navigator.push()调用之间,FirstWidget 已正确注册并didPushNext FirstWidget触发回调。

有关更多详细信息,请参阅flutter 问题 #55949 。