Flutter 颤振无限滚动始终重置视图

Flutter 颤振无限滚动始终重置视图,flutter,Flutter,我有一个简单的无限滚动从API加载项目。我的期望加载更多项目后,如果使用新项目和我的视图端口更新列表,则不会重置 这是我的页面 class ArticleListPage extends StatelessWidget { final _scrollController = ScrollController(); final Color color = Colors.black; ArticleListBloc _articleListBloc; @override Wid

我有一个简单的无限滚动从API加载项目。我的期望加载更多项目后,如果使用新项目和我的视图端口更新列表,则不会重置

这是我的页面

class ArticleListPage extends StatelessWidget {
  final _scrollController = ScrollController();
  final Color color = Colors.black;
  ArticleListBloc _articleListBloc;

  @override
  Widget build(BuildContext context) {
    _articleListBloc = BlocProvider.of<ArticleListBloc>(context);
    return Scaffold(
      backgroundColor: color,
      body: BlocBuilder<ArticleListBloc, ArticleListState>(
        builder: (context, ArticleListState state) {
          if (state.searching) {
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.white,
              ),
            );
          } else {
            return NotificationListener<ScrollNotification>(
              onNotification: _handleScrollNotification,
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: calculateListItemCount(state),
                controller: _scrollController,
                physics: AlwaysScrollableScrollPhysics(),
                itemBuilder: (context, index) {
                  return index >= state.listItems.length
                      ? Center(
                          child: CircularProgressIndicator(),
                        )
                      : ArticleListViewItem(article: state.listItems[index]);
                },
              ),
            );
          }
        },
      ),
    );
  }

  bool _handleScrollNotification(ScrollNotification notification) {
    if (notification is ScrollEndNotification &&
        _scrollController.position.extentAfter == 0) {
      _articleListBloc.add(GetArticles());
    }
    return false;
  }

  int calculateListItemCount(ArticleListState state) {
    if (state.hasReachedEndOfResults) {
      return state.listItems.length;
    } else {
      return state.listItems.length + 1;
    }
  }
}
class ArticleListPage扩展了无状态小部件{
final _scrollController=scrollController();
最终颜色=Colors.black;
ArticleListBloc_ArticleListBloc;
@凌驾
小部件构建(构建上下文){
_articleListBloc=BlocProvider.of(上下文);
返回脚手架(
背景颜色:颜色,
正文:BlocBuilder(
生成器:(上下文,ArticleListState){
if(state.search){
返回中心(
子对象:循环压缩机指示器(
背景颜色:Colors.white,
),
);
}否则{
返回通知侦听器(
onNotification:_handleScrollNotification,
子项:ListView.builder(
收缩膜:对,
itemCount:calculateListItemCount(状态),
控制器:\ u滚动控制器,
物理:AlwaysScrollableScrollPhysics(),
itemBuilder:(上下文,索引){
返回索引>=state.listItems.length
?中心(
子对象:CircularProgressIndicator(),
)
:ArticleListViewItem(article:state.listItems[索引]);
},
),
);
}
},
),
);
}
bool_handleScrollNotification(滚动通知通知){
如果(通知为ScrollEndNotification&&
_scrollController.position.extentAfter==0){
_add(GetArticles());
}
返回false;
}
int calculateListItemCount(ArticleListState状态){
if(state.hasReachedEndOfResults){
返回状态.listItems.length;
}否则{
返回状态.listItems.length+1;
}
}
}
还有我的集团

class ArticleListBloc extends Bloc<ArticleListEvent, ArticleListState> {
  final ArticleDataSource dataSource;

  ArticleListBloc(this.dataSource) : super(ArticleListState.initial());

  @override
  Stream<ArticleListState> mapEventToState(ArticleListEvent event) async* {
    String searchKeyword = state.searchKeyword;
    int pageNumber = state.pageNumber;
    bool hasReachEndResult = state.hasReachedEndOfResults;
    BuiltList<Article> currentArticles = state.listItems;
    if (event is SetKeyword) {
      searchKeyword = event.keyword;
      pageNumber = 0;
      currentArticles = new BuiltList<Article>();
      hasReachEndResult = false;
    }
    if (!hasReachEndResult) {
      yield state.rebuild((b) => b..searching = true);
      final articles = await dataSource.getArticles(pageNumber, searchKeyword);
      if (articles.isEmpty) {
        hasReachEndResult = true;
      } else {
        hasReachEndResult = false;
      }
      yield ArticleListState.success(currentArticles + articles, pageNumber + 1,
          searchKeyword, hasReachEndResult);
    }
  }
}
class ArticleListBloc扩展了Bloc{
最终文章数据源数据源;
ArticleListBloc(this.dataSource):super(ArticleListState.initial());
@凌驾
Stream mapEventToState(ArticleListEvent事件)异步*{
字符串searchKeyword=state.searchKeyword;
int pageNumber=state.pageNumber;
bool hasReachEndResult=state.hasreachendendofresults;
BuiltList currentArticles=state.listItems;
if(事件为SetKeyword){
searchKeyword=event.keyword;
页码=0;
currentArticles=新构建列表();
hasReachEndResult=false;
}
如果(!hasReachenResult){
屈服状态.重建((b)=>b..search=true);
final articles=wait dataSource.getArticles(页码、搜索关键字);
如果(条款I为空){
hasReachEndResult=true;
}否则{
hasReachEndResult=false;
}
收益ArticleListState.success(当前文章+文章,页码+1,
searchKeyword,hasReachEndResult);
}
}
}
不知何故,在搜索(加载更多)后,我可以看到第一个项目再次被重新绘制,并且我被迫再次向下滚动,尽管这些项目已正确添加到列表中


我是否需要某种
跳过
变量才能转到第一个新添加的项目?我还缺少什么?

问题在于构建小部件函数中的第一个if条件。应该是

         if (state.listItems.isEmpty) {
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.white,
              ),
            );
          }
这样一来,
CircularProgressIndicator
将仅在第一次搜索期间绘制,而随后的搜索及其进度已由中的指示器处理

                itemBuilder: (context, index) {
                  return index >= state.listItems.length
                      ? Center(
                          child: CircularProgressIndicator(),
                        )
                      : ArticleListViewItem(article: state.listItems[index]);
                },

问题在于build小部件函数中的第一个if条件。应该是

         if (state.listItems.isEmpty) {
            return Center(
              child: CircularProgressIndicator(
                backgroundColor: Colors.white,
              ),
            );
          }
这样一来,
CircularProgressIndicator
将仅在第一次搜索期间绘制,而随后的搜索及其进度已由中的指示器处理

                itemBuilder: (context, index) {
                  return index >= state.listItems.length
                      ? Center(
                          child: CircularProgressIndicator(),
                        )
                      : ArticleListViewItem(article: state.listItems[index]);
                },