Flutter Error: RangeError (index): Invalid value: Not in range 0..2, inclusive: 3
AndroidFlutterDartAndroid Problem Overview
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:
Android Solutions
Solution 1 - Android
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;
}
Solution 2 - Android
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.
Solution 3 - Android
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
Solution 4 - Android
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];
},
);
}
},
),
Solution 5 - Android
In my case, my itemCount:list.lenght
parameter was fine but somewhere in my listTile,
I used wrong parameter for list.indexWhere()
function .When I fix function, error was gone.
Solution 6 - Android
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
Solution 7 - Android
This mainly occurs when you are using wrong index value to fetch data from list. in my case, I was doing the same mistake.
Solution 8 - Android
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.
Solution 9 - Android
Widget getListView(){
var itemList = getListElement();
var list = ListView.builder(
itemCount: itemList.length,
itemBuilder:(context, index){
return ListTile(
title: Text(itemList[index]),
);
}
);
return list;
}