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

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

问题描述

我在 Flutter 中有一个带有按钮的 StatefulWidget,它使用 Navigator.push() 将我导航到另一个 StatefulWidget.在第二个小部件上,我正在更改全局状态(某些用户首选项).当我从第二个小部件返回到第一个时,使用 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 的回答虽然正确,但可能更简洁一些,实际上使用 push 而不是 OP 询问的 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 Container(
      color: Colors.green,
      child: Column(
        children: <Widget>[
          RaisedButton(
            onPressed: () => Navigator.pop(context),
            child: 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: Column(
        children: <Widget>[
          RaisedButton(
            child: Text("next"),
            onPressed: () async {
              final value = await Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => SecondPage()),
                ),
              );
              setState(() {
                color = color == Colors.white ? Colors.grey : Colors.white;
              });
            },
          ),
        ],
      ),
    );
  }
}

void main() => runApp(
      MaterialApp(
        builder: (context, child) => SafeArea(child: child),
        home: 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 中继承的Widget 的一个例子是应用程序的主题,尽管他们在一个小部件中定义它,而不是像我在这里那样直接构建它.

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 Container(
      color: Colors.green,
      child: Column(
        children: <Widget>[
          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天全站免登陆