将标签栏与动画列表一起使用会导致重复的全局键错误

Using tabbar with animated list results in duplicate global key error

我正在尝试使用 3 个选项卡和这些选项卡中的 AnimatedList 实现 Flutter 的选项卡栏。我想使用相同的列表并根据每个选项卡(过去的任务、今天的任务和未来的任务)过滤列表,但是在我实现选项卡栏和动画列表的过程中,我收到关于重复全局键的错误小部件树。 https://pastebin.com/iAW6DH9m。处理此错误的最佳方法是什么?感谢您的帮助。

编辑:我试过用这个方法来解决这个问题。 虽然它确实修复了我的错误,但我无法访问密钥上的 "currentstate" 方法,无法将更多项目添加到列表中。然后我尝试使用 using GlobalKey 的类似方法,它导致重复全局键的类似错误。

这是我的标签栏实现

import 'package:flutter/material.dart';
import 'search_widget.dart';
import 'animatedlist_widget.dart';

class Dashboard extends StatefulWidget {
  @override
  _DashboardState createState() => _DashboardState();
}

class _DashboardState extends State<Dashboard> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        centerTitle: true,
        actions: <Widget>[
          new IconButton(icon: new Icon(Icons.grid_on), onPressed: null)
        ],
        title: new Text('Dashboard'),
        elevation: 0,
      ),
      floatingActionButton: new FloatingActionButton(
          onPressed: () {
            _onFabPress(context);
          },
          child: new Icon(Icons.add)),
      body: Scaffold(
        appBar: new SearchWidget(
          onPressed: () => print('implement search'),
          icon: Icons.search,
          title: 'Search',
          preferredSize: Size.fromHeight(50.0),
        ),
        body: DefaultTabController(
          length: 3,
          child: Scaffold(
            appBar: PreferredSize(
              preferredSize: Size.fromHeight(kToolbarHeight),
              child: Container(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: new TabBar(
                      unselectedLabelColor: Colors.black45,
                      labelColor: Colors.white,
                      indicator: CustomTabIndicator(),
                      tabs: <Widget>[
                        new Tab(text: "Past"),
                        new Tab(text: "Today"),
                        new Tab(text: "Future")
                      ]),
                ),
              ),
            ),
            body: new TabBarView(
              children: <Widget>[
                AnimatedTaskList(),
                AnimatedTaskList(),
                AnimatedTaskList()
              ],
            )
          ),
        ),
      ),
    );
  }

  void _onFabPress(context) {
    AnimatedTaskList().addUser();
  }
    /*showModalBottomSheet(
        context: context,
        builder: (BuildContext bc) {
          return Container(
              child: new Wrap(children: <Widget>[
            new TextField(
                decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    hintText: 'Enter Task Title')),
            new TextField(
                decoration: InputDecoration(
              border: OutlineInputBorder(),
              hintText: 'Enter Task Details',
            )),
          ]));
        });
  }*/
}

class CustomTabIndicator extends Decoration {
  @override
  BoxPainter createBoxPainter([onChanged]) {
    // TODO: implement createBoxPainter
    return new _CustomPainter(this, onChanged);
  }
}

class _CustomPainter extends BoxPainter {
  final CustomTabIndicator decoration;

  _CustomPainter(this.decoration, VoidCallback onChanged)
      : assert(decoration != null),
        super(onChanged);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    // TODO: implement paint
    assert(configuration != null);
    assert(configuration.size != null);

    final indicatorHeight = 30.0;
    final Rect rect = Offset(
            offset.dx, (configuration.size.height / 2) - indicatorHeight / 2) &
        Size(configuration.size.width, indicatorHeight);
    final Paint paint = Paint();
    paint.color = Colors.blueAccent;
    paint.style = PaintingStyle.fill;
    canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(30)), paint);
  }
}

这是我的动画列表class:

import 'package:flutter/material.dart';

final GlobalKey<AnimatedListState> _listKey = GlobalKey();

class AnimatedTaskList extends StatefulWidget {

  void addUser() {
    int index = listData.length;
    listData.add(
      TaskModel(
        taskTitle: "Grocery Shopping",
        taskDetails: "Costco",
      ),
    );
    _listKey.currentState
        .insertItem(index, duration: Duration(milliseconds: 500));
  }

  @override
  _AnimatedTaskListState createState() => _AnimatedTaskListState();
}

class _AnimatedTaskListState extends State<AnimatedTaskList> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: SafeArea(
          child: AnimatedList(
              key: _listKey,
              initialItemCount: listData.length,
              itemBuilder:
                  (BuildContext context, int index, Animation animation) {
                return Card(
                    child: FadeTransition(
                        opacity: animation,
                        child: ListTile(
                          title: Text(listData[index].taskTitle),
                          subtitle: Text(listData[index].taskDetails),
                          onLongPress: () {
                            //todo delete user
                          },
                        )));
              })),
    );
  }
}

class TaskModel {
  TaskModel({this.taskTitle, this.taskDetails});
  String taskTitle;
  String taskDetails;
}

List<TaskModel> listData = [
  TaskModel(
    taskTitle: "Linear Algebra",
    taskDetails: "Chapter 4",
  ),
  TaskModel(
    taskTitle: "Physics",
    taskDetails: "Chapter 9",
  ),
  TaskModel(
    taskTitle: "Software Construction",
    taskDetails: "Architecture",
  ),
];

我通过移动

解决了我的问题
final GlobalKey<AnimatedListState> _listKey = GlobalKey(); 

进入我的 _AnimatedTaskListState class,并向我的 AnimatedTaskList 添加构造函数和私钥 class

  final GlobalKey<AnimatedListState> _key;
  AnimatedTaskList(this._key);

  @override
  _AnimatedTaskListState createState() => _AnimatedTaskListState(_key);

然后在我的选项卡栏实现中,我更改了它以反映我的新构造函数

AnimatedTaskList(GlobalKey<AnimatedListState>(debugLabel: "key 1"));
AnimatedTaskList(GlobalKey<AnimatedListState>(debugLabel: "key 2"));
AnimatedTaskList(GlobalKey<AnimatedListState>(debugLabel: "key 3"));