flutter - 颤振无限滚动总是重置视图
问题描述
我有一个简单的无限滚动,它从 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 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);
}
}
}
不知何故,在搜索(加载更多)之后,我可以看到第一个项目再次重绘,尽管项目已正确添加到列表中,但我不得不再次向下滚动。
我是否需要某种skip
变量才能转到第一个新添加的项目?我在这里还缺少什么?
解决方案
问题在于构建小部件函数中的第一个 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]);
},
推荐阅读
- entity-framework - 存储在数据库中的 EF 迁移与原始代码不同
- javascript - HTML 标记到 javascript createElement
- mysql - 在laravel中获取一个标题下相同字符串的所有记录
- typescript - 使用过滤的 keyof 类型索引多态“this”类型
- python - 在 Heroku 上安装 numpy 的问题:找不到满足要求 numpy==1.20.1 的版本(来自 -r /tmp/build_795c7f47/requirements.txt
- asp.net - 如何在VB中的if not语句中使用多个条件
- react-native - React Native Expo 实时聊天功能
- java - JSONArrayRequest 没有响应或错误响应
- cmake - 完成 protobuf_generate 后运行命令
- python - Matplotlib fontproperties 仅更改第一个轴刻度