当前位置: 首页 > news >正文

Flutter Beta 版本引入 ScrollCacheExtent ,并修复长久存在的 shrinkWrap NaN 问题

在最近发布的 Flutter 3.43.0-0.1.pre 这个 Beta 版本里,官方在 Framework 层面对 ScrollView / Viewport / ShrinkWrappingViewport 做了一个比较有意思的修改:

  • 引入ScrollCacheExtent,废弃cacheExtent + cacheExtentStyle
  • 修复RenderShrinkWrappingViewport在无约束下 cacheExtent 可能变成 NaN 的问题
  • 重构 Viewport cache 计算路径

这次修改涉及 rendering 层核心代码,属于Viewport 底层重构,暂时看来修改的作用是正向的,应该不至于引起类似之前《Flutter 3.41 iOS 键盘负优化:一个代码洁癖引发的负优化》 的问题。

根据 #181092 的修改内容,这次修改范围主要涉及:

rendering/viewport.dart widgets/scroll_view.dart widgets/page_view.dart widgets/list_view.dart widgets/grid_view.dart

对应源码的影响有:

RenderViewportBaseRenderViewportRenderShrinkWrappingViewportViewportShrinkWrappingViewportScrollViewListViewPageView

所以,虽然看起来只是一个小 feature 和一个 bug fix,但是其实这个调整并不是 Widget 层的小改动,而是Viewport 渲染路径修改

所以才会需要挑出来聊一聊。

首先是ScrollCacheExtent,在之前的实现里,Viewport cache 主要由这两个字段控制:

double cacheExtentCacheExtentStylecacheExtentStyle

相关逻辑为:

switch(cacheExtentStyle){caseCacheExtentStyle.pixel:calculatedCacheExtent=cacheExtent;caseCacheExtentStyle.viewport:calculatedCacheExtent=mainAxisExtent*cacheExtent;}

涉及的关键变量是:

mainAxisExtent=viewport size

而问题也就出现在这里,因为ShrinkWrappingViewport的特殊性,当ScrollView设置shrinkWrap = true的时候,ScrollView.buildViewport就会会创建ShrinkWrappingViewport

ScrollView.buildViewport->ShrinkWrappingViewport->RenderShrinkWrappingViewport

ShrinkWrappingViewport的特点就是 viewport size 由子节点决定,而不是通过父约束,这就意味着mainAxisExtent可能不是y一个有限的值 ,也就是类似以下的场景:

SingleChildScrollView->ListView(shrinkWrap:true)
Column->ListView(shrinkWrap:true)

这些情况下父布局在主轴方向是 unbounded ,所以ShrinkWrappingViewport会得到constraints.maxExtent = infinity的情况,也就是最终:

mainAxisExtent=infinity

这乍一看没什么问题,但cacheExtent逻辑没有考虑这个情况,因为在旧逻辑里:

viewport cache mode=cacheExtentStyle.viewport

也就是

calculatedCacheExtent=mainAxisExtent*cacheExtent

如果这时候mainAxisExtent = infinity,那就会infinity * 0.5 = infinity,以至于在后续布局计算里paintExtent\layoutOffset\scrollOffset都可能出现infinity - infinity,也就是结果为 NaN ,比如:

SingleChildScrollView(child:ListView.builder(shrinkWrap:true,cacheExtent:0.5,cacheExtentStyle:CacheExtentStyle.viewport,itemBuilder:...),)

而在新 API 下,cacheExtentcacheExtentStyle现在变成ScrollCacheExtent,并且内部做了适配,所以这种情况现在不会再报错了:

SingleChildScrollView(child:ListView.builder(shrinkWrap:true,scrollCacheExtent:ScrollCacheExtent.viewport(0.5),),)

所以这里的ScrollCacheExtent不是简单的把两个参数编程一个,而是内部做了重构,首先是在 viewport.dart 内部提供了:

ScrollCacheExtent.pixels()ScrollCacheExtent.viewport()

对应内部实现了新的 Viewport 计算逻辑:

_calculateCacheOffset(mainAxisExtent)_calculatedCacheExtent=_scrollCacheExtent._calculateCacheOffset(mainAxisExtent)

这个情况下 cache 集中计算,并且避免 style + value 分离,其中「NaN 修复」的关键在于RenderShrinkWrappingViewport,对应核心修改为:

if(!mainAxisExtent.isFinite)cacheExtent=0

因为对于 infinite viewport 来说,实际上 already builds all children ,所以根本不需要 Cache ,而这个修改也会涉及PageView\ListView\GridView\CustomScrollView等常用控件。

所以这也是一个相对昂贵的性能配置选项。

所以这个ScrollCacheExtent的修改,本质上是:

  • 重构 Viewport cache API
  • 修复ShrinkWrappingViewport在无约束下cacheExtent计算 NaN 的问题
  • 统一ScrollView/Viewport/RenderViewport的缓存逻辑

虽然逻辑改动看起来好像改的不多,但是涉及的文件和地方还是挺多的,从长远来看,这个修改还是比较有意义的,至少之前经常遇到的 NaN 问题终于不要自己处理了。

链接

https://github.com/flutter/flutter/pull/181092

http://www.jsqmd.com/news/501731/

相关文章:

  • 前端-小米商城静态版复刻总结
  • HCIP-AI-EI Developer V2.5 第五、六章笔记
  • GEE案例分析:基于Dynamic World 数据的农用地识别活跃与休耕农田
  • java之抽象类和接口
  • 万爱通礼品卡怎么回收最划算?线上流程分享 - 团团收购物卡回收
  • Python基于卷积神经网络的学情分析系统【附源码、文档说明】
  • 一键生成以假乱真的扫描件!LookScanned:cpolar 内网穿透实验室第 786成功挑战
  • 2026年3月郑州黄金回收店推荐排行榜单:五大机构客观对比与深度评测分析 - 品牌推荐
  • 洛谷:P1554 [USACO06DEC] 梦中的统计 Dream Counting B
  • 博世 HBA 液压制动辅助系统性能规范详解
  • 把杂乱网址装进口袋!Dashlet 轻量仪表盘 : cpolar 内网穿透实验室第 757 个成功挑战
  • 不学 Python,Java 也能调大模型?15 分钟跑通第一个 AI 接口(Java 架构师的 AI 工程笔记 01)
  • Java架构设计:密码加密设计最佳实践(从入门到工业级落地)
  • 什么是原型链(Prototype Chain)?proto和prototype的关系与区别是什么?
  • 【零基础入门】Python机器视觉第五阶段:目标检测实战(YOLOv8)
  • Q312B三菱主基板
  • SpringBoot 配置文件核心用法(Properties YAML)
  • Python 全栈实战 · 第8章
  • 《QGIS快速入门与应用基础》226:添加地图框工具(布局工具栏)
  • 【Vue入门】scoped与组件通信
  • 2026年推荐防水补漏公司,江苏宋家防水服务特色大剖析 - 工业品牌热点
  • Swin Transformer模型如何利用Patch Merging模仿CNN卷积神经网络
  • vscode安装wsl插件并连接wsl
  • 新160个CrackMe 002号:abexcm5 逆向分析
  • 揭秘支付宝立减金快速回收技巧,省钱绝招分享 - 团团收购物卡回收
  • 场景适配|六大城市高端腕表维修养护指南(按品牌+佩戴场景精准适配) - 时光修表匠
  • 04-C#.Net-委托和事件-面试题
  • 【前端】基础知识类汇总(长期更新)
  • 《QGIS快速入门与应用基础》225:页面背景颜色与网格
  • 网易企业邮箱价格多少?2026年最新套餐年费与收费标准详细介绍 - 品牌2026