perf(discover): 剧场与新片页网格改为按行懒加载
flutter-ci / test (push) Failing after 19m39s

双列网格原来是两个 Column 一次性建出所有卡片,翻几页后上百张卡连同封面都留在树上;
现在改成按行的 SliverList,只构建可见行,剧场页/新片页/搜索结果的滚动容器一并换成 sliver。
搜索结果、加载失败等状态同步改成 sliver,滚动位置与下拉刷新行为保持不变。
This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-29 11:38:21 +08:00
1 parent 4aaa5bbd60
commit fe49527dd8
6 files changed
+193 -145

No files matched your search

+3 -2
View File
@@ -384,7 +384,7 @@ void main() {
expect(refresh.edgeOffset, 52);
expect(
tester.widget<ListView>(_verticalFeed).physics,
tester.widget<CustomScrollView>(_verticalFeed).physics,
AppPullToRefresh.physics,
);
await tester.drag(_verticalFeed, const Offset(0, 240));
@@ -396,7 +396,8 @@ void main() {
}
final Finder _verticalFeed = find.byWidgetPredicate(
(widget) => widget is ListView && widget.scrollDirection == Axis.vertical,
(widget) =>
widget is CustomScrollView && widget.scrollDirection == Axis.vertical,
);
Future<void> _pumpTheater(
+16 -25
View File
@@ -8,6 +8,7 @@ import 'package:fruitshorts/core/data/models/home_feed.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/widgets/app_pull_to_refresh.dart';
import 'package:fruitshorts/pages/discover/discover_view.dart';
import 'package:fruitshorts/pages/discover/widgets/drama_grid.dart';
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
@@ -234,25 +235,26 @@ void main() {
await tester.pumpAndSettle();
final list = find.byKey(const Key('new-releases-list'));
expect(tester.widget<ListView>(list).physics, AppPullToRefresh.physics);
await tester.drag(list, const Offset(0, -400));
await tester.pump();
expect(_countKeys('home-drama-card-'), 20);
expect(
tester.widget<CustomScrollView>(list).physics,
AppPullToRefresh.physics,
);
// 网格懒加载后只保留可见行,页数直接看传给网格的剧目数。
List<Drama> gridDramas() => tester
.widget<SliverDramaGrid>(find.byKey(const Key('new-releases-all-grid')))
.dramas;
expect(gridDramas(), hasLength(20));
// jumpTo 不发滚动通知,滑到底后再拖一下才会触发加载。
final position = _scrollPosition(tester, const Key('new-releases-list'));
position.jumpTo(position.maxScrollExtent);
await tester.pump();
expect(find.byKey(const Key('new-releases-load-more')), findsOneWidget);
await tester.pump(const Duration(milliseconds: 299));
expect(_countKeys('home-drama-card-'), 20);
await tester.pump(const Duration(milliseconds: 1));
await tester.drag(list, const Offset(0, -60));
await tester.pump();
expect(_countKeys('home-drama-card-'), 40);
expect(find.byKey(const Key('new-releases-load-more')), findsOneWidget);
await tester.pumpAndSettle();
position.jumpTo(position.maxScrollExtent);
await tester.pumpAndSettle();
expect(find.byKey(const Key('new-releases-no-more')), findsNothing);
expect(gridDramas(), hasLength(40));
position.jumpTo(0);
await tester.pump();
@@ -262,10 +264,7 @@ void main() {
await tester.pumpAndSettle();
expect(repository.fetchCalls, beforeRefresh + 1);
expect(position.pixels, 0);
await tester.drag(list, const Offset(0, -400));
await tester.pump();
expect(_countKeys('home-drama-card-'), 20);
expect(gridDramas(), hasLength(20));
});
testWidgets('should_refresh_reserve_without_load_more', (tester) async {
@@ -327,14 +326,6 @@ ScrollPosition _scrollPosition(WidgetTester tester, Key listKey) {
return tester.state<ScrollableState>(scrollable.first).position;
}
int _countKeys(String prefix) => find
.byWidgetPredicate((widget) {
final key = widget.key;
return key is ValueKey<String> && key.value.startsWith(prefix);
})
.evaluate()
.length;
class _CountingCatalogRepository extends FakeCatalogRepository {
_CountingCatalogRepository({super.dramas});