如何在Flutter的Screen2编辑名称并同步更新至Screen1?
Flutter 编辑页面返回后无法更新列表项名称的问题
我刚学Flutter,完成了入门教程的应用开发,已经实现列表/卡片视图切换、单词删除图标,还把无限显示改成了仅显示20个单词。现在想通过命名路由实现第二个页面:点击第一个页面的名称跳转到编辑页,修改完成后回到第一个页面能看到更新后的名称。已创建编辑页、输入框和路由,但名称更新始终不生效,特此求助,以下是我的代码:
import 'package:flutter/material.dart'; import 'package:english_words/english_words.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Startup Names', initialRoute: '/', routes: { '/': (context) => const RandomWords(), EditScreen.routeName: (context) => EditScreen(), }, ); } } class RandomWords extends StatefulWidget { const RandomWords({super.key}); @override State<RandomWords> createState() => _RandomWordsState(); } class _RandomWordsState extends State<RandomWords> { final _suggestions = <WordPair>[]; final _saved = <WordPair>{}; final _biggerFont = const TextStyle(fontSize: 20); String selected = ''; bool isList = true; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Startup Names'), actions: [ IconButton( icon: const Icon(Icons.bookmark_border_sharp), onPressed: _pushSaved, tooltip: 'Favorites', ), IconButton( icon: isList ? const Icon(Icons.grid_view) : const Icon(Icons.list), onPressed: () { setState(() { isList = !isList; }); }, tooltip: isList ? 'Card mode' : 'List mode', ), ], ), body: isList ? lista() : cards()); } Widget lista() { return ListView.builder( padding: const EdgeInsets.all(16.0), itemCount: 40, itemBuilder: (context, i) { if (i.isOdd) return const Divider(); final index = i ~/ 2; if (index >= _suggestions.length) { _suggestions.addAll(generateWordPairs().take(10)); } return favorites(_suggestions[index], index); }, ); } Widget cards() { return GridView.builder( padding: const EdgeInsets.all(16.0), itemCount: 20, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 5, mainAxisSpacing: 5, mainAxisExtent: 100), itemBuilder: (context, i) { if (i >= _suggestions.length) { _suggestions.addAll(generateWordPairs().take(10)); } return Card(child: favorites(_suggestions[i], i)); }); } Widget favorites(WordPair pair, int index) { final alreadySaved = _saved.contains(pair); return ListTile( title: Text( pair.asPascalCase, style: _biggerFont, ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(alreadySaved ? Icons.favorite : Icons.favorite_border), color: alreadySaved ? Colors.red : null, tooltip: alreadySaved ? 'Remove favorite' : 'Favorite', onPressed: () { setState(() { if (alreadySaved) { _saved.remove(pair); } else { _saved.add(pair); } }); }, ), IconButton( icon: const Icon(Icons.delete), color: Colors.black87, tooltip: 'Remove from list', onPressed: () { setState(() { _suggestions.remove(pair); _saved.remove(pair); }); }, ), ], ), onTap: () { selected = pair.asPascalCase; Navigator.pushNamed(context, '/second', arguments: Argumentos(index, selected)); }); } void _pushSaved() { Navigator.of(context).push( MaterialPageRoute<void>( builder: (context) { final tiles = _saved.map( (pair) { return ListTile( title: Text( pair.asPascalCase, style: _biggerFont, ), ); }, ); final divided = tiles.isNotEmpty ? ListTile.divideTiles( context: context, tiles: tiles, ).toList() : <Widget>[]; return Scaffold( appBar: AppBar( title: const Text('Favorites'), ), body: ListView(children: divided), ); }, ), ); } } class EditScreen extends StatefulWidget { static const routeName = '/second'; const EditScreen({super.key}); @override State<EditScreen> createState() => _EditScreenState(); } class _EditScreenState extends State<EditScreen> { final first = TextEditingController(); final second = TextEditingController(); @override Widget build(BuildContext context) { final argumentos = ModalRoute.of(context)?.settings.arguments as Argumentos; String selected = argumentos.name; return Scaffold( appBar: AppBar( title: Text('Edit word'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text("What's the new name?", style: TextStyle(fontSize: 30)), const SizedBox(height: 30), Padding( padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 16), child: TextFormField( controller: first, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'First part of the name', ), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 16), child: TextFormField( controller: second, decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Second part of the name', ), ), ), const SizedBox(height: 20), ElevatedButton( child: const Text('Change it'), onPressed: () { selected = (WordPair(first.text, second.text)).toString(); Navigator.pushNamed(context, '/'); }, ), ], ), )); } } class Argumentos { final int id; final String name; Argumentos(this.id, this.name); }
解决方案
问题核心
- 编辑页修改后仅更新了局部变量,未将新数据回传给主页面
- 使用
Navigator.pushNamed返回主页面会重新创建页面实例,而非回到原页面 - 主页面未监听编辑页的返回结果,也未更新数据源
_suggestions
修改步骤
1. 主页面接收编辑页返回的新数据
修改favorites方法中的onTap逻辑,用async/await接收返回值并更新数据源:
onTap: () async { final result = await Navigator.pushNamed( context, EditScreen.routeName, arguments: Argumentos(index, pair.asPascalCase), ); if (result != null && result is WordPair) { setState(() { // 更新列表中的对应项 _suggestions[index] = result; // 同步更新收藏列表(如果该单词已收藏) if (_saved.contains(pair)) { _saved.remove(pair); _saved.add(result); } }); } },
2. 编辑页携带数据返回主页面
修改编辑页按钮的onPressed逻辑,用Navigator.pop携带新创建的WordPair返回:
ElevatedButton( child: const Text('Change it'), onPressed: () { if (first.text.isNotEmpty && second.text.isNotEmpty) { final newPair = WordPair(first.text, second.text); Navigator.pop(context, newPair); } }, ),
3. 优化编辑页初始化体验(可选)
打开编辑页时自动填充原单词的拆分内容:
@override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { final argumentos = ModalRoute.of(context)?.settings.arguments as Argumentos; final parts = argumentos.name.split(' '); if (parts.length == 2) { first.text = parts[0]; second.text = parts[1]; } }); }
4. 清理无用变量
删除主页面中未使用的String selected = '';变量。
内容的提问来源于stack exchange,提问作者Akarnell
相关产品推荐
相关产品推荐

