弹出时强制Flutter导航器重新加载状态 [英] Force Flutter navigator to reload state when popping

查看:123
本文介绍了弹出时强制Flutter导航器重新加载状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Flutter中有一个带有按钮的 StatefulWidget ,它使用 StatefulWidget > Navigator.push()。在第二个小部件上,我正在更改全局状态(某些用户首选项)。当我从第二个小部件回到第一个小部件时,使用 Navigator.pop(),第一个小部件处于旧状态,但我想强制重新加载它。任何想法如何做到这一点?我有一个主意,但看起来很丑:

I have one StatefulWidget in Flutter with button, which navigates me to another StatefulWidget using Navigator.push(). On second widget I'm changing global state (some user preferences). When I get back from second widget to first, using Navigator.pop() the first widget is in old state, but I want to force it's reload. Any idea how to do this? I have one idea but it looks ugly:


  1. 弹出来删除第二个小部件(当前一个)

  2. 再次弹出以删除第一个小部件(上一个)

  3. 按下第一个小部件(应强制重绘)


推荐答案

在这里您可以做几件事。 @Mahi的正确答案可能会更简洁一些,实际上是使用OP询问时使用push而不是showDialog。这是一个使用 Navigator.push 的示例:

There's a couple of things you could do here. @Mahi's answer while correct could be a little more succinct and actually use push rather than showDialog as the OP was asking about. This is an example that uses Navigator.push:

import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: Colors.green,
      child: new Column(
        children: <Widget>[
          new RaisedButton(
            onPressed: () => Navigator.pop(context),
            child: new Text("back"),
          ),
        ],
      ),
    );
  }
}

class FirstPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new FirstPageState();
}

class FirstPageState extends State<FirstPage> {

  Color color = Colors.white;

  @override
  Widget build(BuildContext context) {
    return new Container(
      color: color,
      child: new Column(
        children: <Widget>[
          new RaisedButton(
              child: new Text("next"),
              onPressed: () {
                Navigator
                    .push(
                  context,
                  new MaterialPageRoute(builder: (context) => new SecondPage()),
                )
                    .then((value) {
                  setState(() {
                    color = color == Colors.white ? Colors.grey : Colors.white;
                  });
                });
              }),
        ],
      ),
    );
  }
}

void main() => runApp(
      new MaterialApp(
        builder: (context, child) => new SafeArea(child: child),
        home: new FirstPage(),
      ),
    );

但是,还有另一种方法可以很好地满足您的用例。如果您将 global 用作会影响首页构建的内容,则可以使用 InheritedWidget 定义您的全局用户首选项,并且每次更改它们时,您的FirstPage都会重新生成。甚至可以在如下所示的无状态窗口小部件中使用(但也应该在有状态窗口小部件中使用)。

However, there's another way to do this that might fit your use-case well. If you're using the global as something that affects the build of your first page, you could use an InheritedWidget to define your global user preferences, and each time they are changed your FirstPage will rebuild. This even works within a stateless widget as shown below (but should work in a stateful widget as well).

应用程序的主题是flutter中的InheritedWidget的一个示例,尽管它们

An example of inheritedWidget in flutter is the app's Theme, although they define it within a widget instead of having it directly building as I have here.

import 'package:flutter/material.dart';
import 'package:meta/meta.dart';

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: Colors.green,
      child: new Column(
        children: <Widget>[
          new RaisedButton(
            onPressed: () {
              ColorDefinition.of(context).toggleColor();
              Navigator.pop(context);
            },
            child: new Text("back"),
          ),
        ],
      ),
    );
  }
}

class ColorDefinition extends InheritedWidget {
  ColorDefinition({
    Key key,
    @required Widget child,
  }): super(key: key, child: child);

  Color color = Colors.white;

  static ColorDefinition of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(ColorDefinition);
  }

  void toggleColor() {
    color = color == Colors.white ? Colors.grey : Colors.white;
    print("color set to $color");
  }

  @override
  bool updateShouldNotify(ColorDefinition oldWidget) =>
      color != oldWidget.color;
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var color = ColorDefinition.of(context).color;

    return new Container(
      color: color,
      child: new Column(
        children: <Widget>[
          new RaisedButton(
              child: new Text("next"),
              onPressed: () {
                Navigator.push(
                  context,
                  new MaterialPageRoute(builder: (context) => new SecondPage()),
                );
              }),
        ],
      ),
    );
  }
}

void main() => runApp(
      new MaterialApp(
        builder: (context, child) => new SafeArea(
              child: new ColorDefinition(child: child),
            ),
        home: new FirstPage(),
      ),
    );

如果您使用继承的小部件,则不必担心观看页面的弹出状态推送,这将适用于基本用例,但在更复杂的情况下可能最终会遇到问题。

If you use inherited widget you don't have to worry about watching for the pop of the page you pushed, which will work for basic use-cases but may end up having problems in a more complex scenario.

这篇关于弹出时强制Flutter导航器重新加载状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆