Как исправить rangeError при вставке элемента в AnimatedList (подключен к базе данных Firebase) - PullRequest
0 голосов
/ 13 октября 2019

Я вставляю документ в базу данных и обновляю currentState GlobalKey для AnimatedList, чтобы сообщить ему о добавленном новом элементе Я получаю rangeError

, но посленесколько мгновений перестройка виджета исправляет экран ошибок и мой новый элемент добавляет нормально

Я думаю, проблема в том, что при получении данных из базы данных не хватает времени для обновления, потому что я использую это:

sleep(const Duration(seconds:1));

ошибка не появляется

Также я проверял количество элементов в списке и количество документов snapshot.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),
        ),
      );
  }
}

1 Ответ

1 голос
/ 13 октября 2019

Вероятно, вам следует 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);
  });
}
...