【问题标题】:setState not working with Navigator.of(context)setState 不适用于 Navigator.of(context)
【发布时间】:2020-01-12 21:06:02
【问题描述】:

我正在尝试使用颤振Example app part 2。简而言之: 第一页:它构建了一个无限的单词列表,您可以在其中添加/删除一些您喜欢的单词 还有一个第二页列出了所有喜欢的单词。我们可以通过应用栏的actions: <Widget>[IconButton(icon: Icon(Icons.list), onPressed: _pushSaved)]访问第二个页面

我稍微修改了代码,所以第二页使用相同的列表生成器_buildWordsList,因此它们共享相同的布局/样式,我们也可以单击第二页上的单词取消收藏它们。

可悲的是,当我在第二页点击喜欢的单词时,虽然它会从所选单词中删除它,但它仍然显示(因为它仍然是最喜欢的)

这里是“重要”代码(and here is a gist with all the code):

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWordsState extends State<RandomWords> {
  final List<WordPair> _suggestions = <WordPair>[];
  final List<WordPair> _saved = <WordPair>[]; // Add this line.
  # ...

  Widget _buildWordsList(WordPair itemAt(int index)) {
    return ListView.builder(
      ...
      itemBuilder: (BuildContext context, int i) {
        ...
        return _buildRow(item);
      },
    );
  }

  Widget _buildRow(WordPair pair) {

    return ListTile(
      title:  Text(pair),
      ...
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

  WordPair _suggestionsBuilder(int index) {
    // ... fill suggestions if needed, then return related index suggestion
    return _suggestions[index];
  }

  WordPair _savedGetter(int index) {
    // ... check if index exists, return null if not
    return _saved[index];
  }

  void _pushSaved() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (BuildContext context) {
          return Scaffold(
              appBar: AppBar(
                title: Text("Favorites suggestions"),
              ),
              body: _buildWordsList(_savedGetter));
        },
      ),
    );
  }

  @override // Add from this line ...
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.list), onPressed: _pushSaved)
        ],
      ),
      body: _buildWordsList(_suggestionsBuilder),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => RandomWordsState();
}

在添加MaterialPageRoute_pushSaved 方法中,即使我将上下文传递给Navigator.of(context).push(,当我在“已保存的建议”页面上,然后单击已保存的建议和行@987654331 @ 被触发,第二个列表不会重绘自身。但我确信它已从 _saved 单词列表中删除,因为当我回到 General 列表时,它不再被选中(心脏不再是红色的)

所以状态被修改,但页面似乎没有订阅一旦加载/推送的更改。只有当我返回主页然后返回保存的建议时,它才会改变。我该如何解决这个问题?

感谢您的阅读。我不知道在哪里寻求任何帮助。这种东西有什么不和谐/松懈吗?

【问题讨论】:

    标签: flutter state


    【解决方案1】:

    这不是一个好的架构。 Navigazor.push() 方法将小部件推送到导航器堆栈上。由于您不会在任何地方弹出导航器堆栈,它们只是堆叠起来。您应该添加一个保存状态数据的全局变量,并使用setState 更新用户界面。在这里查看更多信息:documentation

    【讨论】:

    • 谢谢你的回答,但我有点迷茫有两个原因:(1)我认为Navigator.push 会自动添加一个“返回”按钮,它会自行弹出堆栈(这就是我可以回到第1页),看截图。 (2) 我正在使用setState。虽然这可能不是添加路线和导航的最佳方式,但我再次使用谷歌自己给出的示例。我只是试着理解为什么setState 没有触发子路由来重绘它的 UI
    • 这是因为 setState() 只是更新了它被调用的小部件的 UI 以及它的所有无状态子部件。您推送的小部件不是孩子。它只是被推送到导航器堆栈上。
    • 我明白了。那么我如何使它“依赖”,链接它或在需要时手动触发 UI 更改?使国家全球解决它吗?这是一个好习惯吗?
    猜你喜欢
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 2021-03-14
    • 1970-01-01
    相关资源
    最近更新 更多