首页/新闻资讯/正文详情

Litho Working Ranges 完全指南:用 Sections 预取数据与缓存预热

发布时间:2026/9/27 21:19:50 来源:云帆数科 栏目:资讯中心
Litho Working Ranges 完全指南:用 Sections 预取数据与缓存预热
移动开发UI组件【免费下载链接】lithoA declarative framework for building efficient UIs on Android.项目地址https://gitcode.com/gh_mirrors/li/litho点击查看免费下载导读本文基于 working-ranges.md 展开系统讲解 Litho 的Working Ranges API如何通过定义WorkingRange、注册范围、接收进入/退出事件在列表滚动过程中实现数据预取prefetch与缓存预热cache warming等复杂操作。读完本文你将掌握范围定义、OnRegisterRanges/OnEnteredRange/OnExitedRange三件套的完整用法并理解其底层分发机制WorkingRangeContainer与官方实现BoundaryWorkingRange的原理能够在自己的 RecyclerView/Sections 列表中落地分页加载与预取逻辑。说明本文面向的是基于 Java codegen 的经典 Sections API。若你使用 Kotlin Lazy Collection API可参阅 Lazy Collection 交互文档 中对应的内容。Working Ranges API 概述Working Ranges API 为 Sections 提供了一组外观与可见性事件appearance visibility events当一个 Section 进入或退出视口viewport内外的某个位置区间时框架会触发对应回调。典型场景是当列表最后一个元素即将进入视口时立刻发起网络请求开始预取下一页数据从而消除滚动到底部的等待时间。API 由两部分组成定义范围Defining a range—— 实现WorkingRange接口描述什么位置算在范围内接收范围事件Receiving range events—— 在组件中注册范围并实现进入/退出回调Sections 与范围交互时触发。从源码结构看该能力贯穿 litho-annotations注解定义、litho-processor代码生成与 litho-core运行时容器三个模块。第一部分定义范围Defining a Range实现 WorkingRange 接口要使用 Working Ranges API首先定义一个实现WorkingRange接口的类public class AtLeastPartiallyVisibleRange implements WorkingRange { ... }该接口只要求实现两个函数shouldEnterRange与shouldExitRange。两者签名一致Kotlin 源接口定义见 WorkingRange.ktfun shouldEnterRange( position: Int, firstVisibleIndex: Int, lastVisibleIndex: Int, firstFullyVisibleIndex: Int, lastFullyVisibleIndex: Int ): Boolean fun shouldExitRange( position: Int, firstVisibleIndex: Int, lastVisibleIndex: Int, firstFullyVisibleIndex: Int, lastFullyVisibleIndex: Int ): Boolean参数含义如下参数含义position当前检查的条目在列表中的位置firstVisibleIndex视口内第一个部分或完全可见条目的位置lastVisibleIndex视口内最后一个部分或完全可见条目的位置firstFullyVisibleIndex视口内第一个完全可见条目的位置lastFullyVisibleIndex视口内最后一个完全可见条目的位置firstVisibleIndex/lastVisibleIndex与firstFullyVisibleIndex/lastFullyVisibleIndex共同刻画了当前视口可见范围你的范围判定逻辑就是基于这些值对position做区间运算。使用 shouldEnterRangeshouldEnterRange用于判断条目是否位于用户自定义的范围内。下面的示例判断position 至少部分可见于屏幕Override public boolean shouldEnterRange( int position, int firstVisibleIndex, int lastVisibleIndex, int firstFullyVisibleIndex, int lastFullyVisibleIndex) { return position firstVisibleIndex position lastVisibleIndex; }即只要position落在[firstVisibleIndex, lastVisibleIndex]闭区间内就认为进入了范围此时框架会触发该组件的OnEnteredRange回调。使用 shouldExitRangeshouldExitRange用于判断条目是否位于用户自定义范围之外。下面的示例判断position 完全不可见连部分可见都不算Override public boolean shouldExitRange( int position, int firstVisibleIndex, int lastVisibleIndex, int firstFullyVisibleIndex, int lastFullyVisibleIndex) { return position firstVisibleIndex || position lastVisibleIndex; }即只要position落在可见闭区间之外就认为退出了范围此时框架会触发该组件的OnExitedRange回调。官方内置实现BoundaryWorkingRange仓库在 BoundaryWorkingRange.kt 中提供了一个开箱即用的实现。它以offset定义范围的上下边界position落在[firstVisiblePosition - offset, lastVisiblePosition offset]之间即视为在范围内否则视为在范围外class BoundaryWorkingRange JvmOverloads constructor(private val offset: Int OFFSET) : WorkingRange { override fun shouldEnterRange(...): Boolean isInRange(position, firstVisibleIndex, lastVisibleIndex, offset) override fun shouldExitRange(...): Boolean !isInRange(position, firstVisibleIndex, lastVisibleIndex, offset) companion object { private const val OFFSET 1 private fun isInRange( position: Int, firstVisiblePosition: Int, lastVisiblePosition: Int, offset: Int ): Boolean { val lowerBound firstVisiblePosition - offset val upperBound lastVisiblePosition offset return position in lowerBound..upperBound } } }默认offset 1即预取范围是视口上下各多一个条目。你可以通过构造函数传入自定义 offset 来扩大预取窗口——例如想做提前 5 个条目预取传入BoundaryWorkingRange(5)即可。这正是列表最后一个元素接近视口时开始预取这一场景的直接实现。位置粒度 vs 像素粒度:::caution 重要提示 Working ranges 在 ComponentKit 中以像素度量粒度而 Litho 以**位置position即条目序号**度量。这意味着 Litho 只能判断组件是否落在某个位置区间内而无法获知区间内具体有多少像素。 :::这带来一个实际约束你的预取/预热判断只能基于第几个条目无法精确到距视口多少像素。在设计预取阈值时建议结合条目高度估算或直接使用位置差作为阈值。第二部分接收范围事件Receiving Range Events在 LayoutSpec 中注册范围定义好范围后需要在包含RecyclerComponent的LayoutSpec中实现回调函数来接收 enter/exit 事件。第一步是通过OnRegisterRanges把范围注册到组件上LayoutSpec class ListContainerComponentSpec { OnRegisterRanges static void registerWorkingRanges( ComponentContext c, Prop AtLeastPartiallyVisibleRange myRange) { ListContainerComponent.registerPrefetchWorkingRange(c, myRange); } }这里的registerPrefetchWorkingRange是由注解处理器litho-processor中的 WorkingRangeGenerator.java根据范围 name 自动生成的注册方法registerNameWorkingRange(c, workingRange)。进入范围事件OnEnteredRange当组件进入范围时触发OnEnteredRange事件OnEnteredRange(name prefetch) static void onEnteredWorkingRange( ComponentContext c, Prop MyService service) { service.startPrefetch(); }典型用法即是在此发起预取网络请求。注解定义见 OnEnteredRange.java其文档明确指出要让该回调生效必须同时在OnRegisterRanges中完成注册。退出范围事件OnExitedRange当组件退出范围时触发OnExitedRange事件OnExitedRange(name prefetch) static void onExitedWorkingRange( ComponentContext c, Prop MyService service) { service.cancelAllPrefetches(); }典型用法是取消已发出的预取请求例如用户快速滑过大量条目时回收资源。注解定义见 OnExitedRange.java。name 字段为同一 Layout 启用多个范围事件OnEnteredRange与OnExitedRange的name字段用于在同一个 Layout上启用多组范围事件。例如 name 为paginate时自动生成的注册方法就是registerPaginateWorkingRangeOnEnteredRange(name paginate) static void onPaginateEntered(...) { ... } OnExitedRange(name paginate) static void onPaginateExited(...) { ... } OnRegisterRanges static void registerWorkingRanges(ComponentContext c, ...) { ListContainerComponent.registerPaginateWorkingRange(c, myRange); }这样同一个列表可以同时拥有prefetch、paginate、warmCache等多套互不干扰的范围事件分别注册不同的WorkingRange实例。底层原理WorkingRangeContainer 的分发机制理解了 API 用法之后我们来看运行时容器 WorkingRangeContainer.kt 如何支撑这套机制。注册name hashCode 作为键registerWorkingRange将范围以${name}_${workingRange.hashCode()}为键存入workingRanges映射多个共享同一 name 与同一范围对象的组件会被聚合进同一个RangeTuple见 WorkingRangeContainer.kt#L40-L53fun registerWorkingRange( name: String, workingRange: WorkingRange, scopedComponentInfo: ScopedComponentInfo, interStageProps: InterStagePropsContainer? ) { val key ${name}_${workingRange.hashCode()} val rangeTuple workingRanges[key] if (rangeTuple null) { workingRanges[key] RangeTuple(name, workingRange, scopedComponentInfo, interStageProps) } else { rangeTuple.addComponent(scopedComponentInfo) } }RangeTuple内部持有一个scopedComponentInfos列表意味着一个范围可以关联列表中的多个组件实例。分发checkWorkingRangeAndDispatch当列表滚动、视口信息更新时框架调用checkWorkingRangeAndDispatchWorkingRangeContainer.kt#L59-L117。它对每个已注册范围执行如下逻辑通过WorkingRangeStatusHandler查询该组件以globalKey标识当前是否已被标记为在范围内isInRange若当前不在范围内且isEnteringRange(...)内部即调用workingRange.shouldEnterRange返回 true则调用component.dispatchOnEnteredRange(...)触发OnEnteredRange随后调用statusHandler.setEnteredRangeStatus(...)更新状态避免重复触发若当前在范围内且isExitingRange(...)内部即调用workingRange.shouldExitRange返回 true则调用component.dispatchOnExitedRange(...)触发OnExitedRange并更新状态。这个状态机设计保证了 enter/exit 事件只在状态翻转时触发一次不会在每次滚动回调中反复触发避免重复预取。释放时的退出分发dispatchOnExitedRangeIfNeededWorkingRangeContainer.kt#L123-L149用于释放 ComponentTree 时兜底只要组件仍处于在范围内状态就补发一次OnExitedRange确保资源如未完成的预取任务能被清理。调用方见 ComponentTree.java 中的clearWorkingRangeStatusHandler()L1348-L1353。状态跟踪WorkingRangeStatusHandler每个ComponentTree持有独立的 WorkingRangeStatusHandler.kt见 ComponentTree.java#L268-L269以name globalKey为维度记录每个组件实例当前是否处于范围内。这是保证事件边沿触发而非电平触发的关键。实战示例在列表末尾预取下一页综合以上内容一个完整的列表滑动到底前预取下一页示例// 1. 定义范围最后一个可见条目之后的一个位置即可触发 public class PrefetchRange implements WorkingRange { Override public boolean shouldEnterRange( int position, int firstVisibleIndex, int lastVisibleIndex, int firstFullyVisibleIndex, int lastFullyVisibleIndex) { // 当 position 越过当前可见区预取下一页时进入范围 return position lastVisibleIndex 1; } Override public boolean shouldExitRange( int position, int firstVisibleIndex, int lastVisibleIndex, int firstFullyVisibleIndex, int lastFullyVisibleIndex) { return position lastVisibleIndex 1; } } // 2. 在包含 Recycler 的 LayoutSpec 中注册并接收事件 LayoutSpec class FeedComponentSpec { OnRegisterRanges static void registerWorkingRanges( ComponentContext c, Prop PrefetchRange prefetchRange) { FeedComponent.registerPaginateWorkingRange(c, prefetchRange); } OnEnteredRange(name paginate) static void onEnteredWorkingRange( ComponentContext c, Prop PageFetcher fetcher) { fetcher.fetchNextPage(); // 滑动接近末尾时触发分页加载 } OnExitedRange(name paginate) static void onExitedWorkingRange( ComponentContext c, Prop PageFetcher fetcher) { fetcher.cancelPendingFetches(); // 远离范围时取消请求 } }测试验证与更多参考仓库中提供了可直接对照的测试实现LayoutSpec 测试组件LayoutSpecWorkingRangeTesterSpec.kt展示了OnRegisterRangesOnEnteredRange(name boundary)BoundaryWorkingRange()的完整注册与触发链路MountSpec 测试组件MountSpecWorkingRangeTesterSpec.kt说明MountSpec同样支持 Working Ranges注册方法变为MountSpecWorkingRangeTester.registerBoundaryWorkingRange运行时行为测试WorkingRangeContainerTest.kt覆盖了进入/退出/释放分发等边界场景注解定义OnRegisterRanges.java、OnEnteredRange.java、OnExitedRange.java。需要注意OnRegisterRanges在注解源码中已被标记为Deprecated见 OnRegisterRanges.java官方建议未来版本迁移到 Kotlin Lazy Collection API 的交互方案lazycollections-interactions.mdx。但作为经典 Sections 的既有机制其概念与设计对理解 Litho 的可见性驱动编程模型依然有重要参考价值。赞分享移动开发UI组件【免费下载链接】lithoA declarative framework for building efficient UIs on Android.项目地址https://gitcode.com/gh_mirrors/li/litho点击查看免费下载相关推荐Vue Query 数据预取Prefetching完整指南用 queryClient.query 与 infiniteQuery 预热缓存Vue Query 数据预取Prefetching完整指南用 queryClient.query 与 infiniteQuery 预热缓存 导读 在 T前端缓存状态管理DB-GPT缓存策略Redis缓存与数据预热DB GPT缓存策略Redis缓存与数据预热 引言为什么需要缓存策略 在大模型应用开发中数据库查询、模型推理和数据处理都是计算密集型操作。DB GPT作人工智能AI 应用AI AgentRAG本地部署数据分析Rivet缓存策略多级缓存与数据预热机制Rivet缓存策略多级缓存与数据预热机制 还在为高并发场景下的性能瓶颈而头疼Rivet的智能缓存系统帮你轻松应对百万级并发挑战本文将深入解析Rivet如何后端AI Agent人工智能流程编排WebSocket上一篇One-Core-API三步让Windows XP/2003运行现代软件的终极兼容方案下一篇cAdvisor 官方 Go 客户端使用指南对接 REST API 获取容器与机器监控数据创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

WeKnora RAG 知识库本地部署指南:两条命令跑通 Docker,配好模型验检索
WeKnora RAG 知识库本地部署指南:两条命令跑通 Docker,配好模型验检索

WeKnora RAG 知识库本地部署指南:两条命令跑通 Docker,配好模型验检索 【免费下载链接】WeKnora Open-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki. 项目地… · 2026/9/27 21:19:50

PyGithub Lazy Mode 深度解析:按需请求 GitHub API,告别冗余网络开销
PyGithub Lazy Mode 深度解析:按需请求 GitHub API,告别冗余网络开销

开发工具 【免费下载链接】PyGithub Typed interactions with the GitHub API v3 项目地址: https://gitcode.com/gh_mirrors/py/PyGithub 点击查看 免费下载 Lazy Mode(惰性模式)是 PyGithub 提供的一套对象延迟加载机制:开启后… · 2026/9/27 21:19:43

5个免费工具搞定wordpress小工具选项让排名翻倍
5个免费工具搞定wordpress小工具选项让排名翻倍

5个免费工具搞定wordpress小工具选项让排名翻倍 域名服务器搞不懂?别慌,这其实是很多设计师转做前端时最头疼的环节。你明明看着别人网站排在前几,自己折腾半天,wordpress小工具选项里加了一堆插件,结果谷歌和百度都不给流量。其实问… · 2026/9/27 21:19:43

上海网站推广多少钱?老运维给创业团队的速查手册
上海网站推广多少钱?老运维给创业团队的速查手册

上海网站推广多少钱?老运维给创业团队的速查手册 网站被黑挂马不知道怎么办?别慌,先止损再谈优化。我见过太多上海老板,花大几万做了个漂亮官网,结果三天后打开全是博彩广告,后台密码改了也没用。这时候你问“上海网站推广多少钱”,其实是个伪命题。因… · 2026/9/27 22:36:01

会议纪要总出错?实测讯飞听见、钉钉、智在记录三款工具,帮你找到真正靠谱的那一个
会议纪要总出错?实测讯飞听见、钉钉、智在记录三款工具,帮你找到真正靠谱的那一个

你有没有过这样的经历?一场两小时的跨部门会议,明明录了音,转成文字后发现满屏的“嗯嗯啊啊”和术语错乱,核心结论全靠猜;更让人崩溃的是,第二天整理纪要时,根本分不清哪句话是谁说的&#xff0… · 2026/9/27 22:36:01

2026最新百度推广自己怎么做避坑指南
2026最新百度推广自己怎么做避坑指南

2026最新百度推广自己怎么做避坑指南 网站突然被黑挂马,后台弹出大量垃圾链接,SEO排名一夜归零,这种绝望感做过站的人都懂。别慌,2026年的安全环境更复杂,但自救逻辑没变:先断网、再溯源、后加固。很多老板急着找百度客服,其实第一步应该是… · 2026/9/27 22:35:55

青岛永诚网络有限公司从零搭建:搞定备案避坑指南
青岛永诚网络有限公司从零搭建:搞定备案避坑指南

青岛永诚网络有限公司从零搭建:搞定备案避坑指南 备案流程一头雾水,是不是让你对着工信部网站发呆?别急,这种从注册域名到服务器开通,再到ICP备案的 从零搭建… · 2026/9/27 22:35:55

【必藏】解决大模型上下文受限问题:TaoToken 零成本开源方案,让模型突破8k窗口限制
【必藏】解决大模型上下文受限问题:TaoToken 零成本开源方案,让模型突破8k窗口限制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 22:35:55

CiLocks smali代码阅读完整指南:如何在反汇编中快速定位Firestore集合名
CiLocks smali代码阅读完整指南:如何在反汇编中快速定位Firestore集合名

CiLocks smali代码阅读完整指南:如何在反汇编中快速定位Firestore集合名 【免费下载链接】CiLocks Crack Interface lockscreen, Metasploit and More Android/IOS Hacking 项目地址: https://gitcode.com/GitHub_Trending/ci/CiLocks CiLocks 是一款面向 An… · 2026/9/27 22:35:55

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码