How to fix rangeError during inserting item into AnimatedList (connected to Firebase database)

668 Views Asked by At

I'm inserting a document to a database and updating a GlobalKey's currentState of an AnimatedList in order to let it know about new item added i'm geetting rangeError

but after a few moments widget's rebuild fixes error screen and my new item add normally

I think the problem is that getting data from database have not enough time for updating cause when i'm using this:

sleep(const Duration(seconds:1));

the error doesn't appear

Also I was checking the number of items in list and number of documents of snapshot.data, they're not equal during the widget's build which give me an error, but they're equal during the rebuild, which starts just after the error's build The same is about the removing, but there's no error screen during removing

Here's my code:

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

There are 1 best solutions below

0
On BEST ANSWER

You should probably await and then 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);
  });
}