Flutter Can';中间页中使用PUSH替换时的t pop值

Flutter Can';中间页中使用PUSH替换时的t pop值,flutter,Flutter,我有一个页面,它推送另一个页面并等待返回/弹出的值进行处理。如果可能的话,我希望第二页能够委托(让另一页返回值)。大概是这样的: // page 1 Navigator.of(context).push(Page2()).then((value) => print(value)); // process value; perhaps setState or whatever // page 2 Navigator.of(context).pushReplacement(Page3());

我有一个页面,它推送另一个页面并等待返回/弹出的值进行处理。如果可能的话,我希望第二页能够委托(让另一页返回值)。大概是这样的:

// page 1
Navigator.of(context).push(Page2()).then((value) => print(value)); // process value; perhaps setState or whatever

// page 2
Navigator.of(context).pushReplacement(Page3()); // let another page handle the rest

// page 3
Navigator.of(context).pop(99);
然而,第一页上的未来永远不会返回,也永远不会打印值(或以我认为合适的方式处理)。推送替换的原因是我不希望用户返回第2页,如果他们已经进入第三页

下面是一个示例颤振应用程序,你可以试试看我的意思

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Page1(),
    );
  }
}

class Page1 extends StatefulWidget {
  @override
  Page1State createState() => Page1State();
}

class Page1State extends State<Page1> {
  List<int> numbers = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
            Text('Page 1'),
            ...numbers.map((number) => Text(number.toString())),
            RaisedButton(
              child: Text('go to page 2'),
              onPressed: () {
                Navigator.of(context)
                    .push(MaterialPageRoute(builder: (context) => Page2()))
                    .then((number) {
                  if (number != null) {
                    setState(() {
                      numbers.add(number);
                    });
                  }
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
            Text('Ready?'),
            RaisedButton(
              child: Text('Yes'),
              onPressed: () {
                Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (context) => Page3()));
              },
            ),
            RaisedButton(
              child: Text('No'),
              onPressed: () => Navigator.of(context).pop(),
            ),
          ],
        ),
      ),
    );
  }
}

class Page3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
            Text('Pick a number'),
            ...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(
              (number) => RaisedButton(
                child: Text(number.toString()),
                onPressed: () => Navigator.of(context).pop(number),
              ),
            ),
            RaisedButton(
              child: Text('Cancel'),
              onPressed: () => Navigator.of(context).pop(),
            ),
          ],
        ),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
最终颜色深蓝色=颜色。来自argb(255,18,32,47);
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主题:ThemeData.dark().copyWith(脚手架背景颜色:深蓝色),
debugShowCheckedModeBanner:false,
主页:第1页(),
);
}
}
类Page1扩展了StatefulWidget{
@凌驾
Page1State createState()=>Page1State();
}
类Page1State扩展状态{
列表编号=[];
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
子:列(
儿童:[
正文(“第1页”),
…numbers.map((number)=>Text(number.toString()),
升起的按钮(
子项:文本(“转到第2页”),
已按下:(){
导航器(上下文)
.push(MaterialPage路由(生成器:(上下文)=>Page2())
.然后((数字){
如果(数字!=null){
设置状态(){
数字。添加(数字);
});
}
});
},
),
],
),
),
);
}
}
类Page2扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
子:列(
儿童:[
文本(“准备好了吗?”),
升起的按钮(
子项:文本('Yes'),
已按下:(){
导航器.of(上下文).pushReplacement(
MaterialPage路由(生成器:(上下文)=>Page3());
},
),
升起的按钮(
child:Text('No'),
onPressed:()=>Navigator.of(context.pop(),
),
],
),
),
);
}
}
类Page3扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
子:列(
儿童:[
文本(“选择一个数字”),
…[0,1,2,3,4,5,6,7,8,9,10](
(数字)=>升起按钮(
子项:文本(number.toString()),
按下:()=>Navigator.of(context).pop(number),
),
),
升起的按钮(
子项:文本('Cancel'),
onPressed:()=>Navigator.of(context.pop(),
),
],
),
),
);
}
}
我必须澄清用例。第一个页面将从服务器或其他任何地方获取数据,因此我会使用FutureBuilder或类似工具。第二个页面是创建/添加附加项的表单。表单被提交,如果服务器对数据满意,响应将包含新创建的数据。然后我想用显示数据的成功页面替换当前表单页面。当用户弹出此页面时,我希望第一页的列表用数据更新


可以使用类似Bloc、ValueNotifier或类似的花式状态管理,但此页面寿命很短,我希望使用尽可能少的样板代码实现此功能。另外,我发现如果其他页面需要访问,使用这些状态管理类需要添加到MaterialApp的上方/之前。对于一个可能被我的应用程序深埋的页面,我希望避免在main中添加Bloc/ValueNotifier/任何东西。这感觉太重要了。

您可以给
pushReplacement
一个结果,让它返回,就像它被弹出一样

因此,在这种情况下,您可以做的是再次给它一个未来(例如使用补全符),原始推送小部件可以再次等待真正的结果

void方法()异步{
最终完成者=完成者();
最终结果=等待导航仪.pushReplacement(路线,结果:completer.future);
完成(结果);
}

您可以给
pushReplacement
一个返回结果,就像它被弹出一样

因此,在这种情况下,您可以做的是再次给它一个未来(例如使用补全符),原始推送小部件可以再次等待真正的结果

void方法()异步{
最终完成者=完成者();
最终结果=等待导航仪.pushReplacement(路线,结果:completer.future);
完成(结果);
}

在这种情况下,您不能使用navigator.pushReplacement,因为它会触发Page1中的回调运行,而该回调将不再可用。回调需要从/通过第2页获取值;仅当从第2页调用Navigator.pop(上下文)时,才会调用第1页中的“then”

  • 首先在第2页:
  • 现在,您需要弹出2次才能从第3页转到第1页:

    不幸的是,使用Navigator.of(context.popintil)这是不可能的

    A)丑陋且危险的版本-此操作不需要命名路由

    Navigator.of(context).pop(); 
    Navigator.of(context).pop(number);
    
    也许您也应该在第一个弹出窗口中包含返回值(数字),以确保它正确到达不确定第二行中的pop是否会在稍后使用此解决方案结束

    B)也要等待第2页中的导航响应(如第1页),然后在第3页中弹出一次,然后在第2页中弹出一次-此操作不需要命名路由

    Navigator.of(context).pop(); 
    Navigator.of(context).pop(number);
    
    也许是
    import 'package:flutter/material.dart';
    
    final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
          debugShowCheckedModeBanner: false,
          home: Page1(),
          initialRoute: '/page1',
          onGenerateRoute: (settings) {
            switch (settings.name) {
              case '/page1':
                return MaterialPageRoute(
                  settings: RouteSettings(name: '/page1', arguments: Map()),
                  builder: (_) => Page1(),
                );
              default:
                return null;
            }
          },
        );
      }
    }
    
    class Page1 extends StatefulWidget {
      @override
      Page1State createState() => Page1State();
    }
    
    class Page1State extends State<Page1> {
      List<int> numbers = [];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('Page 1'),
                ...numbers.map((number) => Text(number.toString())),
                RaisedButton(
                  child: Text('go to page 2'),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute(builder: (_) => Page2())).then((_) {
                      final Map arguments = ModalRoute.of(context).settings.arguments as Map;
                      final int number = arguments['number'] ?? null;
                      if (number != null) {
                        setState(() {
                          numbers.add(number);
                        });
                      }
                    });
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class Page2 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('Ready?'),
                RaisedButton(
                  child: Text('Yes'),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute(builder: (context) => Page3()));
                  },
                ),
                RaisedButton(
                  child: Text('No'),
                  onPressed: () => Navigator.of(context).pop(),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class Page3 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('Pick a number'),
                ...[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(
                      (number) => RaisedButton(
                    child: Text(number.toString()),
                    onPressed: () {
                      Navigator.of(context).popUntil((route) {
                        if (route.settings.name == '/page1') {
                          (route.settings.arguments as Map)['number'] = number;
                          return true;
                        } else {
                          return false;
                        }
                      });
                    },
                  ),
                ),
                RaisedButton(
                  child: Text('Cancel'),
                  onPressed: () => Navigator.of(context).pop(),
                ),
              ],
            ),
          ),
        );
      }
    }