【问题标题】:ListView.builder itemCount not updatingListView.builder itemCount 未更新
【发布时间】:2020-08-23 11:41:42
【问题描述】:

我有一个小部件,它返回一个 ListView.builder,当用户到达列表视图的底部时,将加载列表视图的项目作为小部件的参数传递。但是当加载项目时,itemCount 不会更新,如果打印 value 参数,我会得到正确数量的项目,但我会得到一个索引错误,其中先例值为范围...... 这是我的日志:

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,
      );
  }
}

【问题讨论】:

  • 请分享onBottomListReachedCallback()方法的代码
  • 我真的不明白你为什么想要那个,但我编辑了我的帖子

标签: listview flutter builder


【解决方案1】:

您必须调用 queryResult.addAll(res['users']); 方法来更新已渲染的小部件 setState 方法。

目前您的结果已添加到 queryResults 数组,但它不会触发重新构建您的 ListView 小部件,因为您必须在 setState() 方法中调用它。

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

【讨论】:

  • 不,在列表上调用 setState,否则列表不会出现范围错误。我已经尝试过了,但它并没有改变任何东西。我找到了一个解决方案,但这个解决方案对我来说并不令人满意:如果我在加载数据之前将 isWaiting 设置为 true,则列表会消失并重新出现并且它可以工作。但我不希望列表消失...
【解决方案2】:

错误是由我的列表而不是 listView 引起的,我只是忘记在 didUpdate 中调用 initState 中的所有代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2020-06-22
    • 2020-10-25
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多