На одном экране (a StatelessWidget
) мы отображаем список слов. Один
слово можно редактировать на втором экране (a StatefulWidget
) через
TextField
.
Возвращаем измененное слово через
Navigator.pop
, но задание с пометкой "неэффективно" просто
что. Использование words.map
создает совершенно новый список, и хотя это
является замыканием, без индекса в words
мы не можем хранить
вернуть измененное слово.
Использование List.asMap()
решит эту проблему, отправив индекс, но
List.asMap().forEach()
не вернет список, который мы можем использовать для
дети Column
.
Что ближе всего к Dart List.asMap().forEach(), возвращающему список?
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: WordsWidget(
words: ["apples", "oranges"])));
}
class EditWordWidget extends StatefulWidget {
String word;
EditWordWidget({super.key, required this.word});
@override
State<EditWordWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<EditWordWidget> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController(text: widget.word);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Edit Word')),
body: Column(
children: [
Row(children: [Text('Word: '),
Container(
width: 100,
child: TextField(
controller: _controller,
onSubmitted: (String value) {
widget.word = value;
},
)),
]),
ElevatedButton(
onPressed: () {
Navigator.pop(context, widget.word);
},
child: const Text('Done'),
)
]
),
);
}
}
class WordsWidget extends StatelessWidget {
List<String> words;
WordsWidget({Key? key, required this.words}) : super(key: key) {}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Words')),
body: Center(
child: Column(
children: words.map((word) =>
Row(
children: [
Text('${word} '),
ElevatedButton(
onPressed: () async {
final new_word = await Navigator.push(
context,
MaterialPageRoute(builder:
(context) => EditWordWidget(word: word)),
);
word = new_word; // ineffectual
},
child: const Text('Edit'),
),
],
),
).toList(),
),
),
);
}
}
Я думаю, вы слишком усложняете это. Если вам нужен индекс в List
, просто повторите с индексами.
children: [
for (var i = 0; i < words.length; i += 1)
Row(
children: [
Text('${words[i]} '),
ElevatedButton(
onPressed: () async {
// ...
words[i] = new_word;
},
child: const Text('Edit'),
),
],
),
],
В качестве альтернативы package: collection предоставляет метод расширения mapIndexed, который позволит вам сделать:
children: words.mapIndexed((i, word) => Row(...)).toList(),
Обратите внимание, что хотя описанные выше подходы мутируют words
List
, они не будут иметь никакого видимого эффекта в вашем приложении Flutter, поскольку WordsWidget
— это StatelessWidget
. Чтобы правильно перестроить его дерево виджетов, вы также должны изменить его на StatefulWidget
и переместить мутацию words[i] = new_word;
в обратный вызов setState
.
просмотрите протокол Map, и вы увидите aMap.entries.map или aMap.map как возможности, которые при необходимости создают либо новую карту, либо новый список.