ListView.builder itemCount не обновляется - PullRequest
0 голосов
/ 08 мая 2020

У меня есть виджет, который возвращает 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,
      );
  }
}

Ответы [ 2 ]

0 голосов
/ 09 мая 2020

Ошибка была вызвана моими списками, а не listView, я просто забыл вызвать весь код в моем initState в didUpdate.

0 голосов
/ 08 мая 2020

Вы должны вызвать queryResult.addAll(res['users']); метод inisde setState метод для обновления уже визуализированного виджета.

В настоящее время ваши результаты добавляются в массив queryResults, но он не запускает повторную сборку вашего ListView виджета, для этого вы должны вызвать его внутри метода setState().

 void init() async {
switch (widget.type) {
  case "Followers":
  ....
  setState((){
   queryResult.addAll(res['users']);
   ...
 });
...