diff --git a/lib/pages/home/home_view.dart b/lib/pages/home/home_view.dart index 6cdb3ff..5f6193f 100644 --- a/lib/pages/home/home_view.dart +++ b/lib/pages/home/home_view.dart @@ -161,24 +161,18 @@ class _HomeTabsState extends State<_HomeTabs> { } Widget _body(BuildContext context) { - final pages = [ - _recommend(context), - _recommendDiscover(context), - FollowingPage( + final builders = [ + _recommend, + _recommendDiscover, + (context) => FollowingPage( onGoHome: () => logic.select(0), favoriteController: context.read(), historyRequest: logic.followingHistoryRequest, visible: logic.tab == 2, ), - _my(context), + _my, ]; - return IndexedStack( - index: logic.tab, - children: [ - for (var index = 0; index < pages.length; index++) - TickerMode(enabled: logic.tab == index, child: pages[index]), - ], - ); + return _LazyTabStack(index: logic.tab, builders: builders); } Widget _recommend(BuildContext context) { @@ -248,3 +242,42 @@ class _HomeTabsState extends State<_HomeTabs> { logic.select(tab); } } + +/// 四个根 tab 的容器:只有被访问过的 tab 才真正构建并常驻。 +/// +/// 冷启动时只建推荐页,其余 tab 等第一次切过去再建,省掉三棵子树和它们各自的请求。 +class _LazyTabStack extends StatefulWidget { + const _LazyTabStack({required this.index, required this.builders}); + + final int index; + final List builders; + + @override + State<_LazyTabStack> createState() => _LazyTabStackState(); +} + +class _LazyTabStackState extends State<_LazyTabStack> { + late final Set _visited = {widget.index}; + + @override + void didUpdateWidget(covariant _LazyTabStack oldWidget) { + super.didUpdateWidget(oldWidget); + _visited.add(widget.index); + } + + @override + Widget build(BuildContext context) { + return IndexedStack( + index: widget.index, + children: [ + for (var index = 0; index < widget.builders.length; index++) + TickerMode( + enabled: widget.index == index, + child: _visited.contains(index) + ? widget.builders[index](context) + : const SizedBox.shrink(), + ), + ], + ); + } +} diff --git a/test/following/following_page_test.dart b/test/following/following_page_test.dart index 5acbf0e..3f15012 100644 --- a/test/following/following_page_test.dart +++ b/test/following/following_page_test.dart @@ -36,9 +36,8 @@ void main() { await tester.pumpWidget(_app(catalog: catalog, history: history)); await tester.pumpAndSettle(); - // 首页默认停在推荐 tab:追剧页虽在 IndexedStack 里,也不该提前拉观看历史。 - // 启动时只有「我的」页会拉一次,追剧页若也拉就会变成 2。 - expect(history.recentCalls, 1); + // 首页默认停在推荐 tab:追剧页在启动时还没被构建,不该提前拉观看历史。 + expect(history.recentCalls, 0); await tester.tap(find.byKey(const Key('tab-follow'))); await tester.pumpAndSettle();