惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
T
Tenable Blog
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy International News Feed
S
Security Affairs
NISL@THU
NISL@THU
O
OpenAI News
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Webroot Blog
Webroot Blog
Schneier on Security
Schneier on Security
S
SegmentFault 最新的问题
S
Schneier on Security
G
Google Developers Blog
V
V2EX
C
Check Point Blog
U
Unit 42
Google DeepMind News
Google DeepMind News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
S
Secure Thoughts
博客园 - 司徒正美
Recorded Future
Recorded Future
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
K
Kaspersky official blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
AI
AI
博客园 - 聂微东
N
News and Events Feed by Topic
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
Recent Commits to openclaw:main
Recent Commits to openclaw:main
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
The Hacker News
The Hacker News
The Last Watchdog
The Last Watchdog
Project Zero
Project Zero
W
WeLiveSecurity
博客园 - Franky

美团技术团队

美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团发布基于 N-gram 全新模型:嵌入扩展新范式,实现轻量化 MoE 高效进化 2025美团技术年货,「马」上到来 多维创新打造强泛化智能体模型,LongCat-Flash-Thinking-2601技术报告发布 美团 EvoCUA 刷新开源 SOTA,会用电脑还会持续进化的智能体! 美团 LongCat-Flash-Thinking-2601 发布,工具调用能力登顶开源 SOTA! KuiTest:基于大模型通识的 UI 交互遍历测试 AAAI 2026 | 美团技术团队学术论文精选 2025 | 美团技术团队热门技术文章汇总 美团 LongCat-Video-Avatar 正式发布,实现开源 SOTA 级拟真表现 大模型剪枝新范式:先浓缩,再剪枝——DenoiseRotator技术解读 LongCat 上线 AI 生图!精准高效,AI 创作不设限 美团发布 LongCat-Image 图像生成模型,编辑能力登顶开源 SOTA AI Coding与单元测试的协同进化:从验证到驱动 R-HORIZON:探索长程推理边界,复旦NLP&美团LongCat联合提出LRMs能力评测新框架 美团 LongCat 发布 AMO-Bench:突破 AIME 评测饱和困境,重新定义 LLM 数学上限 美团 LongCat Interaction 团队发布大模型交互系统技术报告 WOWService 美团 LongCat 团队发布全模态一站式评测基准 UNO-Bench 美团开源LongCat-Audio-Codec,高效语音编解码器助力实时交互落地 NeurIPS 2025 | 美团技术团队论文精选 LongCat-Flash-Omni正式发布并开源:开启全模态实时交互时代 美团 LongCat 团队发布 VitaBench:基于复杂生活场景的交互式 Agent 评测基准 LongCat-Video 视频生成模型正式发布,探索世界模型的第一步 ICCV 2025 | 美团论文精选及多模态推理竞赛冠军方法分享 从0到1建设美团数据库容量评估系统 可验证过程奖励在提升大模型推理效率中的探索与实践 LongCat-Flash-Thinking 正式发布,更强、更专业,保持极速! 开源 | InfiniteTalk:无限长虚拟人视频生成的新范式 美团正式发布并开源 LongCat-Flash-Chat,动态计算开启高效 AI 时代 美团 M17 团队开源 Meeseeks 评测集:揭秘大模型的“听话”能力 可信实验白皮书系列08:开放式分析引擎 | 附PDF合集 美团智能头盔研发实践系列02:软件功能篇 美团智能头盔研发实践系列01:硬件设计篇 ACL 2025 | 美团技术团队论文精选 美团开源OIBench与CoreCodeBench:揭示大模型编程能力的真实水平 可信实验白皮书系列07:高阶实验工具 开源 | MeiGen-MultiTalk:基于单张照片实现多人互动演绎 可信实验白皮书系列06:观察性研究 JDK高版本特性总结与ZGC实践 可信实验白皮书系列05:准实验 可信实验白皮书系列04:随机轮转实验 可信实验白皮书系列03:随机对照实验 可信实验白皮书系列02:AB实验基础 可信实验白皮书系列01:从0到1的方法论与实践指南 MTGR:美团外卖生成式推荐Scaling Law落地实践 OR算法+ML模型混合推理框架架构演进 ICLR&CVPR 2025美团技术团队论文精选 行为正则化与顺序策略优化结合的离线多智能体学习算法 预测技术在美团弹性伸缩场景的探索与应用 美团技术年货 | 600+页电子书,算法、工程、测试、数据、安全系列大合集 鸿蒙应用签名实操及机制探究 2024 | 美团技术团队热门技术文章汇总 AutoConsis:UI内容一致性智能检测 CIKM 2024 | 美团技术团队精选论文解读 大前端:如何突破动态化容器的天花板? KDD 2024 OAG-Challenge Cup赛道三项冠军技术方案解读 新一代实验分析引擎:驱动履约平台的数据决策 大众点评技术部包揽KDD 2024 OAG-Challenge Cup赛道全部3项冠军 ACL 2024 | 美团技术团队精选论文解读 KDD 2024 | 美团技术团队精选论文解读 基本功 | 一文讲清多线程和多线程同步 小程序可测性能力建设与实践 SIGIR 2024 | 美团技术团队精选论文解读 Spark向量化计算在美团生产环境的实践 CVPR 2024 | 美团技术团队精选论文解读 基于多模态信息抽取的菜品知识图谱构建 DDD在大众点评交易系统演进中的应用 美团外卖基于GPU的向量检索系统实践 美团大规模KV存储挑战与架构实践 基于接口数据变异的App健壮性测试实践 美团技术年货 | 600+页电子书,前端、后端、算法、测试、运维系列大合集 美团RASP大规模研发部署实践总结 2023 | 美团技术团队热门技术文章汇总 美团到店终端从标准化到数字化的演进之路 AIOps在美团的探索与实践——事件管理篇 美团技术博客十周年,感谢一路相伴 基于UI交互意图理解的异常检测方法 如何利用「深度上下文兴趣网络」提升点击率? 基于模式挖掘的可靠性治理探索 代码变更风险可视化系统建设与实践 美团多场景建模的探索与实践 MJDK 如何实现压缩速率的 5 倍提升? 如何提供一个可信的AB测试解决方案 KDD 2023 | 美团技术团队精选论文解读 美团前端研发框架Rome实践和演进趋势 斩获CVPR 2023竞赛2项冠军|美团街景理解中视觉分割技术的探索与应用 MySQL自治平台建设的内核原理及实践(下) CVPR 2023 | 美团技术团队精选论文解读 超大规模数据库集群保稳系列之三:美团数据库容灾体系建设实践 超大规模数据库集群保稳系列之二:数据库攻防演练建设实践 Robust 2.0:支持Android R8的升级版热修复框架 超大规模数据库集群保稳系列之一:高可用系统 一次「找回」TraceId的问题分析与过程思考 基于AI+数据驱动的慢查询索引推荐 SOTA!目标检测开源框架YOLOv6 3.0版本来啦
Litho在美团动态化方案MTFlexbox中的实践
少宽、腾飞、叶梓 · 2019-09-19 · via 美团技术团队

1. MTFlexbox

MTFlexbox是美团内部应用的非常成熟的一种跨平台动态化解决方案,它遵循了CSS3中提出的Flexbox规范来抹平多平台的差异。MTFlexbox适用于重展示、轻交互的业务场景,与现有HTML、React Native、Weex等跨平台方案相比,MTFlexbox具备着性能高、渲染速度快、兼容性高、原生功能支持度高等优势。但其缺点在于不支持复杂的交互逻辑,不适合复杂交互的业务场景。目前,MTFlexbox已经广泛应用在美团首页、搜索、外卖等重要业务场景。本文主要介绍在MTFlexbox中使用Litho优化性能的实践经验。

1.1 MTFlexbox的原理

MTFlexbox首先定义一份跨平台统一的DSL布局描述文件,前端通过“所见即所得”的编辑器编辑产生布局,客户端下载布局文件后,根据布局中的描述绑定JSON数据,并最终完成视图的渲染。MTFlexbox框架图如下图所示:

图1 MTFlexbox的架构

图中分为五层,分别是:

  • 业务应用层:业务使用MTFlexbox的编辑器定义符合Flexbox规范的DSL文件(XML模版)。
  • 模版下载:负责XML模版下载相关的工作,包括模版缓存、预加载和异常监控等。
  • 模版解析:负责模版解析相关的工作,包括标签节点的预处理、数据绑定、标签节点的缓存复用和数据异常监控等。
  • 视图渲染:负责视图渲染相关的工作,包括把标签结点按照Flexbox规范解析成Native视图,并完成视图属性的设置、点击曝光事件的处理、视图渲染、异常监控等。
  • 自定义标签扩展:提供支持业务扩展自定义标签的能力。

鉴于本篇博客主要涉及渲染相关的内容,下面将着重介绍MTFlexbox从模版解析到渲染的过程。如下图所示,MTFlexbox首先会把XML模版解析成Java中的标签树,然后和JSON数据绑定结合成一颗具有完整数据信息的节点树。至此,模版解析工作就完成了。解析完成的节点树会交给视图引擎进行Native视图树的创建和渲染。

图2 视图模版从解析到渲染

2. MTFlexbox在美团动态化实践中面临的挑战

随着MTFlexbox在美团内部被广泛使用,我们遇到了两个问题:

  • 复杂视图因层级过深,导致滑动卡顿问题。
  • 生成视图耗时过长,导致滑动卡顿问题。

2.1 问题一:视图层级过深

2.1.1 原因分析

MTFlexbox使用的是Flexbox布局,Flexbox布局可以理解成Android LinearLayout布局的一种扩展。Flexbox在布局过程中使用到大量的布局嵌套,如果布局酷炫复杂,无疑会出现布局层级过深、视图树遍历耗时、绘制耗时等问题,最终引发滑动卡顿。下图是美团正在使用的一个模版的视图层级情况(布局最深处有8层):

图3 模版布局层级效果

2.1.2 影响

布局层级过深在布局的计算和渲染过程中会导致过多的递归调用,影响视图的绘制效率,引发页面滑动FPS下降问题,这会直接影响到用户体验。

2.2 问题二:生成视图耗时过长

2.2.1 原因分析

视图生成耗时原因如下图所示:RecyclerView在使用MTFlexbox布局条目时,需要对条目模版进行下载并解析生成节点树,这样会导致生成视图的过程耗时过长。为了提高视图生成速度,我们增加了复用机制,但是滑动过程中,如果遇到新的布局样式仍然需要重新下载和解析。另外,MTFlexbox绑定的数据是未经解析的JSON字符串,所以也要比正常情况下的数据绑定更耗时一些。 正是上面两个原因,导致了MTFlexbox生成视图耗时过长的问题,这也会导致滑动时FPS出现突然下降的现象,产生卡顿感。

图4 视图生成耗时原因分析

2.2.2 影响

由于视图的创建会阻塞主线程,创建视图耗时过长会导致RecyclerView列表滑动时卡顿感明显,也严重影响到了用户体验。

3. Litho

3.1 Litho原理

Litho是一套声明式UI框架,或者说是一个渲染引擎,它主要优化复杂RecyclerView列表的滑动性能问题。Litho实现了视图的细粒度复用、异步计算布局和扁平化视图,可以显著提升滑动性能,减少RecyclerView滑动时的内存占用。详细介绍可以参考美团技术团队之前发布的另一篇博客:Litho的使用及原理剖析

3.2 Litho的优势

通过对Litho原理的了解,我们可以看到Litho主要针对RecyclerView复杂滑动列表做了以下几点优化:

  • 视图的细粒度复用,可以减少一定程度的内存占用。
  • 异步计算布局,把测量和布局放到异步线程进行。
  • 扁平化视图,把复杂的布局拍成极致的扁平效果,优化复杂列表滑动时由布局计算导致的卡顿问题。

扁平化视图刚好可以优化MTFlexbox遇到的视图层级过深的问题。异步计算布局虽然不能直接解决MTFlexbox生成视图耗时过长问题,但是给问题的解决提供了新的思路——异步提前完成视图创建。而且使用Litho还能带来一定程度的内存优化。所以如何将Litho应用到MTFlexbox中,进而来解决MTFlexbox现存的问题,是我们解下来要讨论的重点。

4. Litho + MTFlexbox是怎么解决上述两个问题的?

4.1 解决问题一:视图层级过深问题

Litho实现了布局的扁平化,所以最直接的方式就是使用Litho来替换MTFlexbox现有的视图引擎。视图引擎最主要的作用,是把XML文件解析出来的节点树变成Litho可以展示的视图,所以视图引擎替换的主要工作是把节点树转换成Litho能展示的视图。如下图所示。由于Litho使用的是组件化思想,需要先把节点转化成组件,再把组件树设置给LithoView,而LithoView是Litho用于兼容原生View的容器,它负责把Litho和系统视图引擎桥接起来。

图5 Litho视图引擎从节点到视图的转换

不过视图引擎的替换并不是一帆风顺的,我们在替换过程中也遇到了4个比较大的挑战。

难点一:复用视图无法更新数据问题

问题描述:完成了节点树到组件树的转化以后,我们发现了一个严重的问题——复用的视图无法应用新的数据。

问题分析:当数据发生变化后,MTFlexbox的节点树会对比新旧数据的变更,确定哪些结点需要更新并通知到具体的视图节点,然后更新显示内容(例如:新数据相比旧数据改变了Text,那么只有Text对应的节点会通知对应的视图去更新内容)。Litho组件的Prop属性是不允许更改的,而Litho组件中绝大多数属性都是Prop属性。

解决方案

方案一:使用State属性全局替换所有组件的Prop属性。这种方式的优点在于替换方式相对简单直接,缺点是侵入性强,替换工作量巨大且不符合Litho的思想(尽可能少的去改变组件的状态)。这种方案不是最优解,我们要降低侵入,简单快捷地实现数据更新,于是就产生了方案二,具体如下图所示。

方案二:封装一套Updater组件,用于创建真正展示的组件。Updater组通过State属性监听对应节点的数据变更,当节点数据变化时,可以触发对应节点的更新。

图6 数据更新问题初版解决方案

但在后来的实践过程中,我们发现Litho整个组件树中只要有一个组件有状态更新,便会重新计算整个布局,而每次数据更新少说也会有几十个节点发生变化。频繁的重复计算反而导致性能变得很差。在经过了多种尝试以后,我们找到了最优的解决方案:

图7 数据更新问题最终解决方案

如上图所示,状态更新控制器负责整个视图所有节点的更新操作。在所有数据都更新完成以后,统一交由状态更新控制器触发一遍组件更新。

难点二:Litho不支持层叠布局问题

MTFlexbox并没有完全严格的使用Flexbox布局规范,为了简单实现层叠效果,MTFlexbox自定义了一种新布局规范——Layer布局。Layer布局具有以下两个特点:

  • 特点一:Layer的子视图在z轴上依次层叠展示。
  • 特点二:Layer的子视图默认且只能充满父布局。

原因分析: 由于Litho严格遵守Flexbox布局规范,所以没有现成的Layer组件。

解决方案: 自己实现Layer组件,满足第一个特点很容易,Flexbox本身就支持层叠展示,只需要把子视图设为绝对布局就可以了。但是让子视图默认充满父布局就没有那么简单了,Flexbox布局中没有任何一个属性可以达到这个效果。在经过了若干次组合多个属性的尝试以后,还是没能找到解决方案。既然Layer并不是Flexbox布局的规范,那么我们局限在Flexbox的束缚下,怕是很难找到完美的解决方案。那么,能不能在Litho中绕过Flexbox的约束,自己实现Layer效果呢?想在Litho中突破Flexbox布局的束缚,就需要了解Litho是如何使用Flexbox的。

图8 Litho的布局计算原理

如上图,Litho的Flexbox布局是由Yoga负责布局计算的。每一个Litho组件都会对应一个Yoga节点。但Yoga的布局计算过程是由根节点去统一触发的,子节点没有办法知道自己对应的Yoga节点是何时开始计算,及何时计算结束。这样以来,我们就没有时机去感知到Layer组件的布局是否计算完成,也就没有办法在Layer组件计算完成后去控制Layer子节点的计算。为了解决这个问题,我们做了两件事:

  • 添加布局计算完成的回调,在布局计算完成后由根节点逐层通知子节点计算完成的消息。
  • 拆分Yoga节点树,由Layer自己来控制子节点的计算。

图9 Layer布局的实现原理

如上图所示,把Layer组件伪造成叶子节点,不把Layer组件的子节点设置给Yoga,这样一个Yoga中的布局树就被Layer组件切割开了。当根节点计算完成以后,通知到Layer组件,Layer组件再依次去设置子节点的宽高和位置属性,并触发子节点去完成各自子节点的布局计算。这样就完美地实现了Layer的布局效果。

难点三:Litho图片组件不支持使用网络图片问题

原因分析: Litho的组件是一个属性的集合,Litho期望我们在组件创建时便确定了所有属性的值,所以Litho不支持网络图的展示。如果要支持从网络下载图片,就意味着图片组件用来展示的内容会发生变化。所以Litho自带的图片组件并不支持使用网络图片。

解决方案

方案一:用State属性解决网络图片下载带来的展示内容变化问题。我们在实践中发现,State属性的更新会导致整个布局重新计算,其实替换图片资源不会导致图片组件的大小位置发生变化,根本不需要重新计算布局。为了减少使用State属性导致布局计算频繁的问题,就摒弃了这种方案。

方案二:Litho官方额外提供的异步下载图片组件FrescoImage中使用的是图片代理方式。FrescoImage使用DraweeDrawable来绘制视图,而DraweeDrawable实际上并不具备图片渲染的能力,只是在内部保存了一个真正的Drawable来负责渲染。所以,DraweeDrawable本质上是对真正要展示的图片做了一层代理,当从网络上下载下来真正要展示的图片后,只需要通过替换代理图片就可以完成视图的更新。美团下载图片使用的是Glide,只需要按照这个思路实现自己的GlideDrawable就好了。

难点四:自定义标签扩展的接口不兼容问题

MTFlexbox支持自定义标签的扩展,所以我们在完成基本视图标签的Litho实现以后,还需要支持自定义Tag的扩展,才算完成视图引擎的替换工作。

原因分析: MTFlexbox在设计自定义标签接口时,只提供了允许使用View完成视图扩展的接口,但是Litho实现的视图引擎是使用组件作为视图单元和MTFlexbox对接的,所以接口不能兼容。

解决方案

方案一:重新提供使用Litho组件完成视图扩展的接口。其缺点是,需要MTFlexbox的使用方重新实现已经支持了的自定义标签,工作量较大,所以这种方案被抛弃了。

方案二:Litho中使用业务方已经扩展好的View。其优点是使用方对视图引擎的替换无感知。那么,怎样才能在Litho中使用业务方已经扩展好的View呢?可以先看下面这张图。

图10 Litho对View功能的拆分

我们可以简单的理解成Litho对Android的View做了一个功能拆分,把属性和布局计算的能力放在了组件里面,每一种组件对应一个绘制单元来专门负责绘制。那么对于使用方扩展的标签,我们可以定义一个通用组件来统一承接。在挂载绘制单元时,再去调用使用方扩展的视图去绘制。

优化效果

至此,视图引擎的替换就完成了,整个视图引擎的替换做到了使用方无感知。完美解决了MTFlexbox视图层级深的问题,顺带还优化了部分性能。下面是布局层级优化效果的对比,可以看到相同样式下,使用Litho引擎实现的视图比使用MTFlexbox原生引擎的视图层级要浅很多。

除此之外,还有我们的内存优化成果。下图是美团首页使用MTFlexbox时,内存占用随滑动页数(一页为20条数据)增加而变化的趋势图。可以看到,使用Litho引擎实现的MTFlexbox比使用原生引擎的MTFlexbox在内存占用上能有30M以上的优化。

4.2 解决问题二:生成视图耗时过长

上文提到导致生成视图耗时过长的有两个原因:

(1) MTFlexbox对布局模版的下载和解析耗时。 (2) MTFlexbox绑定时解析数据的耗时。

上文“自定义标签扩展的接口不兼容问题”中介绍过Litho的组件能够独立完成布局计算。另外,Litho组件是轻量级的,所以我们直接把Litho组件作为RecyclerView适配器的数据源。这样就需要在数据解析时提前完成组件的创建,而组件的创建需要用到MTFlexbox的整个解析过程,也就是说,我们把MTFlexbox导致视图生成耗时过长的过程提前在数据层异步完成了。这样就不需要等到视图要展示时再去解析,从而规避了视图生成耗时过长的问题。具体的原理,可以参见Litho的使用及原理剖析一文中的3.2节“异步布局”。

如上图所示,在异步线程中提前完成MTFlexbox布局到Litho组件的转换。当视图真正要展示时,只需要把组件设置给LithoView就可以了。

优化效果

使用Litho引擎实现的滑动列表,在连续滑动过程中不会出现FPS波动问题,而使用MTFlexbox原生引擎实现的滑动列表则波动明显。(数据采集自魅蓝2手机,中低端手机优化效果明显)

5. 总结

经过一段时间的实践,Litho + MTFlexbox给美团App在性能指标上带来了较大的提升。但是还有很多问题待完善,我们后续还会针对以下几点进一步提升效果:

  • 利用Litho组件属性不可变的特点,将提前异步布局进一步扩展为提前渲染出位图,在绘制时直接展示位图,可以进一步提升绘制效率。
  • 优化RecyclerView相关的API,降低侵入性。
  • 解决有点击事件、埋点事件等属性的视图需要降级成View才能使功能生效的问题,进一步优化视图层级。

6.参考资料

Litho官网 Flexbox规范

7. 作者简介

少宽、腾飞、叶梓,美团终端业务研发团队开发工程师。

8. 招聘信息

美团终端业务研发团队的职责是保障平台业务高效、稳定迭代的同时,持续优化用户体验和研发效率。团队负责的业务主要包括美团首页、美团搜索等千万级DAU高频业务以及分享、账号、音/视频等基础业务,支撑和对接外卖、酒店等30多个业务方。

团队通过动态化能力建设,加快业务上线速度,帮助产品团队快速验证业务选型,做出业务决策;通过架构/服务标准化体系建设,提升前后端以及平台与业务线的沟通、合作效率;业务监控和体验优化,有效保障核心业务服务成功率的同时,提升用户使用美团App过程中的稳定性和流畅性。团队开发技术栈包括Android、iOS、ReactNative、Flexbox等。

美团终端业务研发团队现诚聘Android、iOS工程师,欢迎有兴趣的同学投简历至:tech@meituan.com(注明:美团终端业务研发团队)。