#flutter #dart #key
Вопрос:
Я новичок в Flutter, и мне нужна помощь для чайников. Потому что каждый раз, когда я перемещаю свой переупорядочиваемый список, мой терминал отправляет мне сообщение «Возникло еще одно исключение: несколько виджетов использовали один и тот же глобальный ключ».
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:todoapp2/models/global.dart';
import 'package:todoapp2/models/widgets/intray_todo_widget.dart';
import 'package:todoapp2/models/classes/task.dart';
class IntrayPage extends StatefulWidget {
@override
_IntrayPageState createState() => _IntrayPageState();
}
class _IntrayPageState extends State<IntrayPage> {
List<Task> taskList = [];
@override
Widget build(BuildContext context) {
taskList = getList();
return Container(
color: darkGreyColor,
child: _buildReorderableListSimple(context),
// child: ReorderableListView(
// padding: EdgeInsets.only(top: 300),
// children: todoItems,
// onReorder: _onReorder,
// ),
);
}
Widget _buildListTile(BuildContext context, Task item) {
return ListTile(
key: Key(item.taskId),
title: IntrayTodo(
title: item.title, keyValue: '',
),
);
}
Widget _buildReorderableListSimple(BuildContext context) {
return Theme(
data: ThemeData(
canvasColor: Colors.transparent
),
child: ReorderableListView(
// handleSide: ReorderableListSimpleSide.Right,
// handleIcon: Icon(Icons.access_alarm),
padding: EdgeInsets.only(top: 200.0),
children: taskList.map((Task item) => _buildListTile(context, item)).toList(),
onReorder: (oldIndex, newIndex) {
setState(() {
Task item = taskList[oldIndex];
taskList.remove(item);
taskList.insert(newIndex, item);
});
},
),
);
}
void _onReorder(int oldIndex, int newIndex) {
setState(() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final Task item = taskList.removeAt(oldIndex);
taskList.insert(newIndex, item);
});
}
List<Task> getList() {
for (int i = 0; i < 10; i ) {
taskList.add(Task("My first todo " i.toString(), false, i.toString()));
}
return taskList;
}
}
А теперь мое второе досье
import 'package:flutter/material.dart';
import '../global.dart';
class IntrayTodo extends StatelessWidget {
final String title;
final String keyValue;
IntrayTodo({required this.keyValue, required this.title});
@override
Widget build(BuildContext context) {
return Container(
key: Key(keyValue),
margin: EdgeInsets.only(bottom: 5),
padding: EdgeInsets.all(10),
height: 100,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(10)),
boxShadow: [
new BoxShadow(
color: Colors.black.withOpacity(0.5),
blurRadius: 10.0,
),
],
),
child: Row(
children: <Widget>[
/* Radio(
),*/
Row(
children: <Widget>[
Text(title, style: darkTodoTitle,)
],
)
],
),
);
}
}
Образ того, что я пытаюсь сделать
Мое «приложение» работает (глючит из-за ключевой проблемы), это простое приложение для выполнения задач, потому что я пытаюсь учиться и пытаюсь поддерживать свой мозг в форме. Я не знаю, как решить эту проблему. Я очень много гуглил, но ничего не понял, так что это мой последний вариант спросить вас в надежде, что кто-нибудь сможет помочь. Куда мне положить ключ? Я где-то читал «в методе», но я этого не понял.
Код ошибки:
When the exception was thrown, this was the stack:
#2 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2653:12)
#3 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#4 ContainerRenderObjectMixin.visitChildren
(package:flutter/src/rendering/object.dart:3331:14)
#5 RenderSliverMultiBoxAdaptor.visitChildrenForSemantics
(package:flutter/src/rendering/sliver_multi_box_adaptor.dart:398:11)
#6 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#7 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#8 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#9 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#10 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#11 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#12 Iterable.forEach (dart:core/iterable.dart:257:30)
#13 RenderViewportBase.visitChildrenForSemantics
(package:flutter/src/rendering/viewport.dart:222:10)
#14 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#15 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#16 RenderIgnorePointer.visitChildrenForSemantics
(package:flutter/src/rendering/proxy_box.dart:3266:14)
#17 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#18 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#19 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#20 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#21 RenderSemanticsAnnotations.visitChildrenForSemantics
(package:flutter/src/rendering/proxy_box.dart:4663:11)
#22 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#23 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#24 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#25 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#26 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#27 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#28 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#29 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#30 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#31 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#32 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#33 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#34 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#35 RenderObject._getSemanticsForParent.<anonymous closure>
(package:flutter/src/rendering/object.dart:2675:61)
#36 RenderObjectWithChildMixin.visitChildren
(package:flutter/src/rendering/object.dart:3048:14)
#37 RenderObject.visitChildrenForSemantics
(package:flutter/src/rendering/object.dart:2760:5)
#38 RenderObject._getSemanticsForParent
(package:flutter/src/rendering/object.dart:2670:5)
#39 RenderObject._updateSemantics
(package:flutter/src/rendering/object.dart:2631:41)
#40 PipelineOwner.flushSemantics
(package:flutter/src/rendering/object.dart:1076:16)
#41 RendererBinding.drawFrame
(package:flutter/src/rendering/binding.dart:467:21)
#42 WidgetsBinding.drawFrame
(package:flutter/src/widgets/binding.dart:876:13)
#43 RendererBinding._handlePersistentFrameCallback
(package:flutter/src/rendering/binding.dart:328:5)
#44 SchedulerBinding._invokeFrameCallback
(package:flutter/src/scheduler/binding.dart:1144:15)
#45 SchedulerBinding.handleDrawFrame
(package:flutter/src/scheduler/binding.dart:1082:9)
#46 SchedulerBinding._handleDrawFrame
(package:flutter/src/scheduler/binding.dart:998:5)
#50 _invoke (dart:ui/hooks.dart:163:10)
#51 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:259:5)
#52 _drawFrame (dart:ui/hooks.dart:126:31)
(elided 5 frames from class _AssertionError and dart:async)
Another exception was thrown: Duplicate GlobalKey detected in widget tree.
Another exception was thrown: Multiple widgets used the same GlobalKey.
Another exception was thrown: Multiple widgets used the same GlobalKey.
Another exception was thrown: Multiple widgets used the same GlobalKey.
Another exception was thrown: Multiple widgets used the same GlobalKey.
Ответ №1:
Клавиши во флаттере должны быть уникальными. Но в вашем примере кода при перестройке виджета используется тот же ключ с тем же значением.
Что происходит, когда вы создаете ключ, flutter сохраняет его (не как переменную области действия, которая удаляется при выполнении функции), а когда виджет перестраивается, flutter пытается создать новый ключ с тем же значением и обнаруживает, что есть старый ключ с тем же значением, что приводит к этой ошибке
Лучше, если вы определили свои ключи вне функции сборки. Нравится
final Key _key = Key('unique_key');
@override
Widget build(BuildContext context) {
.
.
.
Редактировать: Как здесь упоминалось, ReordarableLitView
Вы можете реорганизовать свой код, чтобы он выглядел так,
чтобы IntrayPage
изменить дочерние элементы списка, чтобы они выглядели так
children: <Widget>[
for (int index = 0; index < taskList.length; index )
_buildListTile(context, taskList[index], index)
],
Измените _buildListTile, чтобы получить индекс и отправить его в IntrayTodo
виджет
Widget _buildListTile(BuildContext context, Task item, int index) {
return ListTile(
key: Key(item.taskId),
title: IntrayTodo(
title: item.title, keyValue: '$index',
),
);
}
Комментарии:
1. Спасибо за ваш комментарий, но я не знаю, как реализовать ваш код, если я попытаюсь сделать ключ в верхней части этого виджета и удалить другие ключи, возникнет огромная ошибка, как и раньше. Это не ваш код, это потому, что я не знаю, как это сделать правильно. Не могли бы вы помочь мне немного больше, если у вас есть время? Эта ключевая проблема действительно трудна для меня…
2. Я просто не понимаю, зачем тебе вообще нужны ключи. приложение будет отлично работать без каких-либо ключей
3. Это приложение для задач, и я хотел сделать переупорядочиваемый список, в котором я могу перетаскивать контейнер с «задачей», и я где-то читал, что они сделали это с помощью ключей. Если у вас есть лучший способ сделать это, просто скажите мне, и я постараюсь это сделать 😀 Это мой самый первый проект.
4.
Another exception was thrown: All children of this widget must have a key.
Это ошибка, когда я удаляю ключи5. Если я прокручу вниз, после пятого задания, он вызовет у меня ту же ошибку. Он все еще работает, но он глючит, приложение не выходит из строя, и я вижу дисплей, но если я перетащу одну задачу из бота наверх или прокрутю вниз в этот момент, я увижу ту же ошибку. Спасибо вам за вашу помощь, правда. Я думаю, что я слишком плох, я не знаю. Это «только» список, черт возьми