У меня есть виджет, который возвращает ListView.builder, элементы списка передаются как параметры виджета, когда пользователь достигает нижней части списка, загружаются новые элементы. Но когда элементы загружены, itemCount не обновляется, если распечатать параметр значения, я получаю нужное количество элементов, но получаю ошибку индекса с предыдущим значением в виде диапазона ... Вот мой журнал:
I/flutter ( 4654): 4
I/flutter ( 4654): 8
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following RangeError was thrown building:
RangeError (index): Invalid value: Not in range 0..3, inclusive: 4
When the exception was thrown, this was the stack:
#0 List.[] (dart:core-patch/growable_array.dart:146:60)
#1 _UsersListViewState.showFollowButton (package:the_spot/services/library/usersListView.dart:167:30)
#2 _UsersListViewState.showResultWidget (package:the_spot/services/library/usersListView.dart:147:43)
#3 _UsersListViewState.build.<anonymous closure> (package:the_spot/services/library/usersListView.dart:75:20)
#4 SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:446:22)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
Посмотрите, что при первой загрузке элементов он распечатывает itemCount (4), и никаких ошибок не произошло (на моем экране у меня тоже есть список элементов), но когда пользователь прокручивает вниз, чтобы обновить список элементов, он печатает новый itemCount (8), но диапазон по-прежнему 4 ...
Вот код виджета (я удалил ненужное содержимое):
import 'package:flutter/material.dart';
import 'package:the_spot/pages/home_page/profile.dart';
import 'package:the_spot/services/library/userProfile.dart';
import 'package:the_spot/services/library/configuration.dart';
import '../../theme.dart';
import '../database.dart';
import 'library.dart';
class UsersListView extends StatefulWidget{
final Configuration configuration;
final List<UserProfile> query;
final VoidCallback onBottomListReachedCallback;
const UsersListView({Key key, this.configuration, this.query, this.onBottomListReachedCallback}) : super(key: key);
@override
_UsersListViewState createState() => _UsersListViewState();
}
class _UsersListViewState extends State<UsersListView> {
List<bool> waitForFollowing = [];
List<bool> friendRequestAlreadyDone = [];
List<bool> waitForSendingFriendRequest = [];
bool isLoadingData = false;
@override
void initState() {
super.initState();
waitForFollowing.clear();
widget.query.forEach((element) {
waitForFollowing.add(false);
waitForSendingFriendRequest.add(false);
if (element.pendingFriendsId
.indexOf(widget.configuration.userData.userId) !=
-1) {
friendRequestAlreadyDone.add(true);
} else {
friendRequestAlreadyDone.add(false);
}
});
}
@override
void didUpdateWidget(UsersListView oldWidget) {
super.didUpdateWidget(oldWidget);
isLoadingData = false;
}
@override
Widget build(BuildContext context) {
print(widget.query.length);
return Expanded(
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo){
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && isLoadingData == false) {
isLoadingData = true;
widget.onBottomListReachedCallback();
}
return true;
},
child: ListView.builder(
padding: EdgeInsets.fromLTRB(
widget.configuration.screenWidth / 20,
widget.configuration.screenWidth / 40,
widget.configuration.screenWidth / 20,
widget.configuration.screenWidth / 40),
itemCount: widget.query.length,
itemBuilder: (BuildContext context, int itemIndex) {
return showResultWidget(itemIndex);
},
shrinkWrap: false,
),
),
);
}
РЕДАКТИРОВАТЬ: как спрашивается, как виджет вызывается:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:the_spot/services/database.dart';
import 'package:the_spot/services/library/configuration.dart';
import 'package:the_spot/services/library/userProfile.dart';
import 'package:the_spot/services/library/usersListView.dart';
import 'package:the_spot/theme.dart';
class FollowersFollowingFriendsPage extends StatefulWidget {
final Configuration configuration;
final UserProfile userProfile;
final String type;
const FollowersFollowingFriendsPage(
{Key key, this.configuration, this.userProfile, this.type})
: super(key: key);
@override
_FollowersFollowingFriendsPageState createState() =>
_FollowersFollowingFriendsPageState();
}
class _FollowersFollowingFriendsPageState
extends State<FollowersFollowingFriendsPage> {
bool isWaiting = true;
List<UserProfile> queryResult = [];
Timestamp index = Timestamp.now();
String noResultMessage;
String appBarTitle;
@override
void initState() {
super.initState();
init();
}
void init() async {
switch (widget.type) {
case "Followers":
{
noResultMessage =
"This user haven't been followed by anyone for the moment.";
appBarTitle = "Users following " + widget.userProfile.pseudo;
Map<String, Object> res = await Database().getFollowersOf(context, widget.configuration.userData.userId, widget.userProfile.userId, index, 10);
queryResult.addAll(res['users']);
index = res['lastTimestamp'];
setState(() {
isWaiting = false;
});
}
break;
case "Following":
{
noResultMessage = "This user doesn't follow anyone for the moment.";
appBarTitle = "Users followed by " + widget.userProfile.pseudo;
Map<String, Object> res = await Database().getFollowingOf(context, widget.configuration.userData.userId, widget.userProfile.userId, index, 4);
queryResult.addAll(res['users']);
index = res['lastTimestamp'];
setState(() {
isWaiting = false;
});
}
break;
case "Friends":
{
noResultMessage = "This user hasn't added friends yet.";
appBarTitle = "Friends of " + widget.userProfile.pseudo;
queryResult = await Database().getUsersByIds(context, widget.userProfile.friends, verifyIfFriendsOrFollowed: true, mainUserId: widget.userProfile.userId);
setState(() {
isWaiting = false;
});
}
break;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: PrimaryColorDark,
appBar: AppBar(title: Text(appBarTitle),),
body: Column(
children: <Widget>[
showQueryResultsWidget(),
],
),
);
}
Widget showQueryResultsWidget() {
if (isWaiting)
return Padding(
padding: EdgeInsets.only(top: widget.configuration.screenWidth / 20),
child: Center(
child: CircularProgressIndicator(),
));
else if (queryResult.length == 0 || queryResult == null)
return Padding(
padding: EdgeInsets.only(top: widget.configuration.screenWidth / 20),
child: Center(child: Text(noResultMessage)),
);
else
return UsersListView(
configuration: widget.configuration,
query: queryResult,
onBottomListReachedCallback: init,
);
}
}