简体   繁体   中英

Flutter Error: RangeError (index): Invalid value: Not in range 0..2, inclusive: 3

I am using a long list in Flutter. All the items are rendering fine but I also receive the following error:

RangeError (index): Invalid value: Not in range 0..2, inclusive: 3

The following is my code:

@override
Widget build(BuildContext context) {
return Container(
  child: getList(),
 );
}

The following is my getList() method:

Widget getList (){
List<String> list = getListItems();
ListView myList = new ListView.builder(itemBuilder: (context, index){
  return new ListTile(
    title: new Text(list[index]),
  );
});
return myList;
}

And the following is my getListItem() method:

List<String> getListItems(){
return ["Faizan", "Usman", "Naouman"];
}

the following is the screenshot of error:

在此处输入图像描述

You should pass the itemCount parameter to the ListView.builder to allow it to know the item count

Widget getList() {
  List<String> list = getListItems();
  ListView myList = new ListView.builder(
    itemCount: list.length,
    itemBuilder: (context, index) {
    return new ListTile(
      title: new Text(list[index]),
    );
  });
  return myList;
}

This error occurs when you run out of values when iterating over an array. In the case of the ListView component missing the itemCount prop, the component attempts to continue to iterate but is unaware when to complete so it eventually continues on out of range (the length of the array).

You could also see this error after running a poorly set up for loop . For example:

var arr = [1, 2, 3];

for (var i=0; i < 4; i++) {
    print(arr[i]);
}

This dart code would result in a range error as well. The array has 3 items yet we attempt to iterate 4 times.

Add the attribute

    itemCount: list.length,

in the listview.builder or gridview.builder.

It works for me on this error:

RangeError (index): Invalid value: Not in inclusive range 0..29: 55

If you are using StreamBuilder then you must use this line of code:

  StreamBuilder(
                  stream: FirebaseFirestore.instance.collection("Tooth")
                  .orderBy("date", descending: false).snapshots() ,
                
                  builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
                 
                    if(snapshot.hasData)
                    {
                      return ListView.builder(
                        itemCount: snapshot.data.docs.length,
                          padding: const EdgeInsets.only( top: 20.0),
                        itemBuilder: (BuildContext context, int index) {
                           DocumentSnapshot ds = snapshot.data.docs[index];
 },
                      );
                    }
                   
                  },
                ),

就我而言,我的itemCount:list.lenght参数很好,但在我的 listTile 的某个地方,我为list.indexWhere()函数使用了错误的参数。当我修复函数时,错误消失了。

For Limited Scroll

The solution is simple you just have to add itemCount to the builder so that the builder allows it to know the item count. Just like the above Code As stated in the this answer

For Infinite Scroll

To do Infinite Scroll use ListView.builder without specifying the itemCount parameter.

  body: ListView.builder(
   itemCount: _photos.length + (_hasMore ? 1 : 0),
    itemBuilder: (context, index) {
      if (index == item.length - _nextPageThreshold) {
        // Here is your manuplated data code
      } else {
        getMoreData();
        return Center(child: CircularProgressIndicator());
      }
    },
  ),

Full code example

class ItemListScreen extends StatefulWidget {
  ItemListScreen({Key key}) : super(key: key);
  @override
  _PhotosListScreenState createState() => _PhotosListScreenState();
}

class _PhotosListScreenState extends State<ItemListScreen> {
  bool _hasMore;
  int _pageNumber;
  bool _error;
  bool _loading;
  final int _defaultPhotosPerPageCount = 10;
  List<Photo> _photos;
  final int _nextPageThreshold = 5;
  @override
  void initState() {
    super.initState();
    _hasMore = true;
    _pageNumber = 1;
    _error = false;
    _loading = true;
    _photos = [];
    fetchPhotos();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Photos App")),
      body: getBody(),
    );
  }

  Widget getBody() {
    if (_photos.isEmpty) {
      if (_loading) {
        return Center(
            child: Padding(
              padding: const EdgeInsets.all(8),
              child: CircularProgressIndicator(),
            ));
      } else if (_error) {
        return Center(
            child: InkWell(
              onTap: () {
                setState(() {
                  _loading = true;
                  _error = false;
                  fetchPhotos();
                });
              },
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Text("Error while loading photos, tap to try agin"),
              ),
            ));
      }
    } else {
      return ListView.builder(
          itemCount: _photos.length + (_hasMore ? 1 : 0),
          itemBuilder: (context, index) {
            if (index == _photos.length - _nextPageThreshold) {
              fetchPhotos();
            }
            if (index == _photos.length) {
              if (_error) {
                return Center(
                    child: InkWell(
                      onTap: () {
                        setState(() {
                          _loading = true;
                          _error = false;
                          fetchPhotos();
                        });
                      },
                      child: Padding(
                        padding: const EdgeInsets.all(16),
                        child: Text("Error while loading photos, tap to try agin"),
                      ),
                    ));
              } else {
                return Center(
                    child: Padding(
                      padding: const EdgeInsets.all(8),
                      child: CircularProgressIndicator(),
                    ));
              }
            }
            final Photo photo = _photos[index];
            return Card(
              child: Column(
                children: <Widget>[
                  Image.network(
                    photo.thumbnailUrl,
                    fit: BoxFit.fitWidth,
                    width: double.infinity,
                    height: 160,
                  ),
                  Padding(
                    padding: const EdgeInsets.all(16),
                    child: Text(photo.title,
                        style: TextStyle(
                            fontWeight: FontWeight.bold, fontSize: 16)),
                  ),
                ],
              ),
            );
          });
    }
    return Container();
  }

  Future<void> fetchPhotos() async {
    try {
      final response = await http.get("https://jsonplaceholder.typicode.com/photos?_page=$_pageNumber");
      List<Photo> fetchedPhotos = Photo.parseList(json.decode(response.body));
      setState(() {
        _hasMore = fetchedPhotos.length == _defaultPhotosPerPageCount;
        _loading = false;
        _pageNumber = _pageNumber + 1;
        _photos.addAll(fetchedPhotos);
      });
    } catch (e) {
      setState(() {
        _loading = false;
        _error = true;
      });
    }
  }
}

class Photo {
  final String title;
  final String thumbnailUrl;
  Photo(this.title, this.thumbnailUrl);
  factory Photo.fromJson(Map<String, dynamic> json) {
    return Photo(json["title"], json["thumbnailUrl"]);
  }
  static List<Photo> parseList(List<dynamic> list) {
    return list.map((i) => Photo.fromJson(i)).toList();
  }
}

to infinite scroll answer credit and for more info Infinite Scrolling ListView

You can use itemCount: snapshot.data.length in ListView.builder .

It will look like this:

 ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) {
                  return Container(
                    child: Text(
                      "${snapshot.data[index]['title']}",
                      style: TextStyle(color: Colors.white),
                    ),
                  );
                });

This mainly occurs when you are using wrong index value to fetch data from list. in my case, I was doing the same mistake.

如果您使用substring并且如果没有正确设置条件,那么您将收到错误

Listview.Builder contains itemcount attribute

Listview.Builder(

itemCount: list.length,

itemBuilde:(context, index)=>

          );

I had this problem inside a GridView, but it had nothing to do with my GridView. I was splitting addresses by commas, ex addresses[index].split(',')[0] , but I came across a address that had no commas which is why I suddenly got this error. Look closely through the debug console to find the exact line of the error, and test every piece of code in your GridView to pinpoint the error.

Widget getListView(){
  var itemList = getListElement();
   var list = ListView.builder(
     itemCount: itemList.length,
       itemBuilder:(context, index){
         return ListTile(
           title: Text(itemList[index]),   
         );
         }
   );
   return list;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM