首页 > 解决方案 > 如何在将项目插入 AnimatedList 期间修复 rangeError(连接到 Firebase 数据库)

问题描述

我正在将文档插入数据库并更新 AnimatedList 的 GlobalKey 的 currentState,以便让它知道添加的新项目 我遇到 rangeError

但片刻之后,小部件的重建修复了错误屏幕,我的新项目正常添加

我认为问题是当我使用这个时,从数据库中获取数据没有足够的时间来更新原因:

sleep(const Duration(seconds:1));

错误没有出现

此外,我正在检查列表中的项目数和快照.data 的文档数,它们在小部件构建期间不相等,这给了我一个错误,但在重建期间它们是相等的,它在错误构建之后开始移除也是一样,但是移除过程中没有错误画面

这是我的代码:

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
////////////////////////////////////////////////////////////////////////
///////////////////////LIST/////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

class Item {
  Item({this.name, this.icon});
  Icon icon;
  String name;
}

class ListScreen extends StatefulWidget {
  @override
  _ListScreenState createState() => _ListScreenState();
}

class _ListScreenState extends State<ListScreen> {
  GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
  int  id;
  bool isInit = true;
  var animatedList;

  _addItem() {
    Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
        .setData({'lastID':--id});
    setState(() {
      Firestore.instance.collection('items').document('ITEM_$id')
          .setData({'name':'Item $id'});
      listKey.currentState.insertItem(0);

      //sleep(const Duration(seconds:1));
    });
  }

  _removeItem(int index, DocumentSnapshot snapshot) {
    setState(() {
      Firestore.instance.runTransaction((Transaction transaction) async{
        await transaction.delete(snapshot.reference);
      });
      listKey.currentState.removeItem(
        index,
            (context, animation) => buildItem(context, snapshot, 0, animation),
        duration: const Duration(milliseconds: 100),
      );
    });
  }

  Widget buildItem(
      BuildContext context, DocumentSnapshot document, int index, Animation<double> animation) {
    return SizeTransition(
      axis: Axis.vertical,
      sizeFactor: animation,
      child: SizedBox(
        child: ListTile(
          title: Text(document['name']),
          onTap: (){
            _removeItem(index, document);
          },
        ),
      ),
    );
  }
// getting last used id
  getData() async {
    return await Firestore.instance.collection('incrementID').getDocuments();
  }
  @override
  Widget build(BuildContext context) {
      getData().then((val) {
        id = int.parse(val.documents[0].data['lastID'].toString());
      });
      return Scaffold(
        body: Directionality(
            textDirection: TextDirection.ltr,
            child: StreamBuilder(
              stream: Firestore.instance.collection('items').snapshots(),
              builder: (context, snapshot) {
                if (!snapshot.hasData ) return const Text('Loading...');
                animatedList = new AnimatedList(
                  key: listKey,
                  initialItemCount: snapshot.data.documents.length,
                  itemBuilder: (context, index, animation) {
                    return
                      buildItem(
                          context, snapshot.data.documents[index], index,
                          animation);
                  },
                );
                return animatedList;
              },
            )),
        floatingActionButton: FloatingActionButton(
          onPressed: _addItem,
          tooltip: 'Decrement',
          child: Icon(Icons.add),
        ),
      );
  }
}

标签: flutterdartgoogle-cloud-firestoreflutter-animatedlist

解决方案


你可能应该await然后insertItem()

_addItem() async {
  await Firestore.instance.collection('incrementID').document('IDINCREMENTATION')
      .setData({'lastID':--id});
  await Firestore.instance.collection('items').document('ITEM_$id')
      .setData({'name':'Item $id'});

  setState(() {
    listKey.currentState.insertItem(0);
  });
}

推荐阅读