From 5649e4c3d4a99e43aedb2a89b599db2ccefeddaf Mon Sep 17 00:00:00 2001 From: Vicky <10212746+haifeng-jiang@user.noreply.gitee.com> Date: Thu, 29 Oct 2026 11:25:31 +0800 Subject: [PATCH] =?UTF-8?q?perf(home):=20=E5=9B=9B=E4=B8=AA=E6=A0=B9=20tab?= =?UTF-8?q?=20=E6=94=B9=E4=B8=BA=E9=A6=96=E6=AC=A1=E5=8F=AF=E8=A7=81?= =?UTF-8?q?=E6=89=8D=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原先 IndexedStack 冷启动就把推荐/发现/追剧/我的四棵子树全建出来,各自还会发请求; 现在只建当前 tab,切过去再建并常驻,冷启动少三页构建和一次观看历史请求。 --- lib/pages/home/home_view.dart | 57 +++++++++++++++++++------ test/following/following_page_test.dart | 5 +-- 2 files changed, 47 insertions(+), 15 deletions(-) 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();