Flutter的原理及美团的实践(下)
Flutter的原理及性能实践
Flutter和原生性能对比
虽然使用原生实现(左)和Flutter实现(右)的全品类页面在实际使用过程中几乎分辨不出来:
但是我们还需要在性能方面有一个比较明确的数据对比。
我们最关心的两个页面性能指标就是页面加载时间和页面渲染速度。测试页面加载速度可以直接使用美团内部的Metrics性能测试工具。对于iOS开发者来说,也可以使用appuploader这类iOS开发助手工具来获取详细的性能数据。appuploader不仅可以帮助开发者上传应用到App Store,还提供了丰富的性能分析功能。
从两个实现的页面分别启动400多次的数据中可以看到,原生实现(AllCategoryActivity)的加载时间中位数为210ms,Flutter实现(FlutterCategoryActivity)的加载时间中位数为231ms。考虑到目前我们还没有针对FlutterView做缓存和重用,FlutterView每次创建都需要初始化整个Flutter环境并加载相关代码,多出的20ms还在预期范围内:
因为Flutter的UI逻辑和绘制代码都不在主线程执行,Metrics原有的FPS功能无法统计到Flutter页面的真实情况,我们需要用特殊方法来对比两种实现的渲染效率。Android原生实现的界面渲染耗时使用系统提供的FrameMetrics接口进行监控:
public class AllCategoryActivity extends WmBaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {getWindow().addOnFrameMetricsAvailableListener(new Window.OnFrameMetricsAvailableListener() {List<Integer> frameDurations = new ArrayList<>(100);@Overridepublic void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, int dropCountSinceLastInvocation) {frameDurations.add((int) (frameMetrics.getMetric(TOTAL_DURATION) / 1000000));if (frameDurations.size() == 100) {getWindow().removeOnFrameMetricsAvailableListener(this);L.w("AllCategory", Arrays.toString(frameDurations.toArray()));}}}, new Handler(Looper.getMainLooper()));}super.onCreate(savedInstanceState);// ...}
}
Flutter在Framework层只能取到每帧中UI操作的CPU耗时,GPU操作在Flutter引擎内部实现,所以要修改引擎来监控完整的渲染耗时:
void Rasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {if (!layer_tree || !surface_) {return;}if (DrawToSurface(*layer_tree)) {last_layer_tree_ = std::move(layer_tree);
#if defined(OS_ANDROID)if (compositor_context_->frame_count().count() == 101) {std::ostringstream os;os << "[";const std::vector<TimeDelta> &engine_laps = compositor_context_->engine_time().Laps();const std::vector<TimeDelta> &frame_laps = compositor_context_->frame_time().Laps();size_t i = 1;for (auto engine_iter = engine_laps.begin() + 1, frame_iter = frame_laps.begin() + 1;i < 101 && engine_iter != engine_laps.end(); i++, engine_iter++, frame_iter++) {os << (*engine_iter + *frame_iter).ToMilliseconds() << ",";}os << "]";__android_log_write(ANDROID_LOG_WARN, "AllCategory", os.str().c_str());}
#endif}
}
测试时我们将两种实现的页面分别打开100次,每次打开后执行两次滚动操作,使其绘制100帧,将这100帧的每帧耗时记录下来:
for (( i = 0; i < 100; i++ )); doopenWMPage allcategorysleep 1adb shell input swipe 500 1000 500 300 900adb shell input swipe 500 1000 500 300 900adb shell input keyevent 4
done
将测试结果的100次启动中每帧耗时取平均値,得到每帧平均耗时情况:
Android原生实现和Flutter版本都会在页面打开的前5帧超过16ms,刚打开页面时原生实现需要创建大量View,Flutter也需要创建大量Widget,后续帧中可以重用大部分控件和渲染节点。
10000帧(100次×100帧每次)中Android原生总平均値为10.21ms,Flutter总平均値为12.28ms,Android原生实现总丢帧数851帧8.51%,Flutter总丢帧987帧9.87%。在原生实现的触摸事件处理和过度绘制充分优化的前提下,Flutter完全可以媲美原生的性能。
总结
Flutter目前仍处于早期阶段,也还没有发布正式的Release版本,不过我们看到Flutter团队一直在为这一目标而努力。虽然Flutter的开发生态不如Android和iOS原生应用那么成熟,许多常用的复杂控件还需要自己实现,有的甚至会比较困难(比如官方尚未提供的ListView.scrollTo(index)功能),但是在高性能和跨平台方面Flutter在众多UI框架中还是有很大优势的。
开发Flutter应用只能使用Dart语言,Dart本身既有静态语言的特性,也支持动态语言的部分特性,对于Java和JavaScript开发者来说门槛都不高,3-5天可以快速上手,大约1-2周可以熟练掌握。对于iOS开发者来说,可以结合appuploader这样的工具来简化开发流程,提高开发效率。
在开发全品类页面的Flutter版本时我们也深刻体会到了Dart语言的魅力,Dart的语言特性使得Flutter的界面构建过程也比Android原生的XML+JAVA更直观,代码量也从原来的900多行减少到500多行(排除掉引用的公共组件)。Flutter页面集成到App后APK体积至少会增加5.5MB,其中包括3.3MB的SO库文件和2.2MB的ICU数据文件,此外业务代码1300行编译产物的大小有2MB左右。
Flutter本身的特性适合追求iOS和Android跨平台的一致体验,追求高性能的UI交互效果的场景,不适合追求动态化部署的场景。Flutter在Android上已经可以实现动态化部署,但是由于Apple的限制,在iOS上实现动态化部署非常困难,Flutter团队也正在和Apple积极沟通。
美团外卖大前端团队将来也会继续在更多场景下使用Flutter实现,并且将实践过程中发现和修复的问题积极反馈到开源社区,帮助Flutter更好地发展。
参考资料
- Flutter中文官网
- Flutter框架技术概览
- Flutter插件仓库
- A Tour of the Dart Language
- A Tour of the Dart Libraries
- Why Flutter Uses Dart
- Flutter Layout机制简介
- Flutter’s Layered Design
- Flutter’s Rendering Pipeline
- Flutter: The Best Way to Build for Mobile?@GOTO conf
- Flutter Engine
- Writing custom platform-specific code with platform channels
- Flutter Engine Operation in AOT Mode
- Flutter’s modes
- Symbolicating-production-crash-stacks
作者简介
els
13. Flutter Engine Operation in AOT Mode
14. Flutter’s modes
15. Symbolicating-production-crash-stacks
作者简介
少杰,美团高级工程师,2017年加入美团,目前主要负责外卖App监控等基础设施建设工作。
相关文章:
Flutter的原理及美团的实践(下)
Flutter的原理及性能实践 Flutter和原生性能对比 虽然使用原生实现(左)和Flutter实现(右)的全品类页面在实际使用过程中几乎分辨不出来: 但是我们还需要在性能方面有一个比较明确的数据对比。 我们最关心的两个页面…...
时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测
时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测 目录 时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab…...
【云安全】云原生- K8S IngressNightmare CVE-2025-1974(漏洞复现完整教程)
漏洞原理 CVE-2025-1974: The IngressNightmare in Kubernetes | Wiz Blog 分两方面: a、配置注入过程 构造一个恶意的Ingress资源,其中注入ssl_engine指令指向恶意共享库向准入控制器验证端点(AdmissionWebhook)发送Admissio…...
Tomcat与Servlet(2)
上篇文章: Tomcat与Servlethttps://blog.csdn.net/sniper_fandc/article/details/147278469?fromshareblogdetail&sharetypeblogdetail&sharerId147278469&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link 上篇文章介绍了To…...
在高数据速度下确保信号完整性的 10 个关键策略
随着越来越多的传感器连接到系统,需要快速、可靠和安全地传输更多数据,对带宽和设计复杂性的需求也在增加。优先考虑的是确保从 A 发送到 B 的信号不会失真。 确保信号完整性 对于设计依赖于持续准确数据流的数据密集型应用程序的工程师来说,…...
2025华中杯数学建模B题完整分析论文(共42页)(含模型、数据、可运行代码)
2025华中杯大学生数学建模B题完整分析论文 目录 一、问题重述 二、问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1解析 4.1.2问题1模型建立 4.1.3问题1样例代码(仅供参考) 4.1.4问题1求解结果(仅供参考&am…...
UE5 自带的视频播放器
文章目录 文件夹准备添加一个文件媒体源方法1方法2 添加一个视频播放器播放视频直接播放使用网格体播放使用UI播放 播放视频的音乐媒体播放器常用的节点设置循环是用绝对路径播放视频,视频无需导入注册播放完成事件 文件夹准备 视频必须被放在Content/Moveis文件下…...
是德科技E5080B网络分析仪深度评测:5G/车载雷达测试实战指南
是德科技E5080B网络分析仪(ENA系列)是一款高性能射频测试仪器,广泛应用于通信、航空航天、半导体等领域,以下是其核心功能详解: 一、核心测试功能 多参数网络分析 S参数测量:支持全双端口S参数测试…...
javaSE————网络编程套接字
网络编程套接字~~~~~ 好久没更新啦,蓝桥杯爆掉了,从今天开始爆更嗷; 1,网络编程基础 为啥要有网络编程呢,我们进行网络通信就是为了获取丰富的网络资源,说实话真的很神奇,想想我们躺在床上&a…...
力扣349 == 两个数组交集的两种解法
目录 解法一:利用 Set 特性高效去重 解法二:双重遍历与 Set 去重 方法对比与总结 关键点总结 题目描述 给定两个整数数组 nums1 和 nums2,要求返回它们的交集。输出结果中的每个元素必须是唯一的,且顺序不限。 示例 输入&…...
笔试专题(十)
文章目录 对称之美(双指针)题解代码 连续子数组最大和(线性dp)题解代码 最长回文子序列(区间dp)题解代码 对称之美(双指针) 题目链接 题解 1. 双指针 2. 用left标记左边的字符串…...
YOLOv12即插即用---RFAConv
1.模块介绍 接受域注意卷积(RFAConv):更聪明地感知空间特征 在传统卷积神经网络中,卷积核参数的共享机制虽有效提升了模型的泛化能力与计算效率,但却忽略了不同空间位置特征在感知范围(即接受域)内的重要性差异。为此,我们提出了一种更具感知能力的模块 —— 接受域注…...
使用datax通过HbaseShell封装writer和reader同步hbase数据到hbase_踩坑_细节总结---大数据之DataX工作笔记008
最近在做大数据相关功能,有个需求,使用datax同步hbase到hbase中,其中还是有很多细节值得记录: 首先来看一下datax的源码中,如果你使用phoenix创建的表,那么 你就需要使用对应的hbase带有sql字样的,reader和writer. 然后如果你使用datax-web来进行测试的,那么,他默认使用的是h…...
Python解决“小D的abc字符变换”问题
小D的“abc”变换问题 问题描述测试样例解题思路代码 问题描述 小D拿到了一个仅由 “abc” 三种字母组成的字符串。她每次操作会对所有字符同时进行以下变换: 将 ‘a’ 变成 ‘bc’ 将 ‘b’ 变成 ‘ca’ 将 ‘c’ 变成 ‘ab’ 小D将重复该操作 k 次。你的任务是输…...
C++学习:六个月从基础到就业——面向对象编程:重载运算符(下)
C学习:六个月从基础到就业——面向对象编程:重载运算符(下) 本文是我C学习之旅系列的第十三篇技术文章,是面向对象编程中运算符重载主题的下篇。本篇文章将继续深入探讨高级运算符重载技术、特殊运算符、常见应用场景和…...
电压模式控制学习
电压模式控制 在开关电源中,大的可分为三大控制模式,分别是电压模式控制,电流模式控制,迟滞模式控制。今天简要介绍下电压模式控制的优缺点。 原理 架构图如下 如图所示,电压模式控制可以分为三部分:误…...
vue3 Ts axios 封装
vue3 Ts axios 封装 axios的封装 import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosHeaders } from axios import qs from qs import { config } from ./config import { ElMessage } from element-plus// …...
GPT,Bert类模型对比
以下是对 BERT-base、RoBERTa-base、DeBERTa-base 和 DistilBERT-base 四个模型在参数量、训练数据、GPU 内存占用、性能表现以及优缺点方面的对比: 模型参数量与训练数据 模型参数量训练数据量BERT-base110MBookCorpus(8亿词) 英文维基百科…...
3.Rust + Axum 提取器模式深度剖析
摘要 深入解读 Rust Axum 提取器模式,涵盖内置提取器及自定义实现。 一、引言 在 Rust 的 Web 开发领域,Axum 作为一款轻量级且高效的 Web 框架,为开发者提供了强大的功能。其中,提取器(Extractor)模式…...
Dify vs n8n vs RAGFlow:2025年AI应用与自动化工作流平台的终极对决
我将为大家整理一份关于 Dify、n8n 和 Ragflow 的最新研究分析,涵盖以下六个方面:功能对比、应用场景、架构设计、集成能力、和使用门槛。我会尽可能引用其官方文档、GitHub 仓库以及社区讨论等权威信息来源。 我整理好后会第一时间通知你查看。 1.Dify、n8n 和 RAGFlow 最新…...
ffmpeg无损转格式的命令行
将ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式转换后.mkv -c:v copy 仅做拷贝视频,不重新编码 -c:a copy 仅做拷贝音频 ,不重新编码...
Flutter 常用命令
1、创建项目 flutter create <项目名称> 示例: flutter create my_app 1.1 参数说明 --org:设置包名(默认 com.example) flutter create --org com.yourcompany my_app -a/-i:指定语言(Kotlin…...
【零基础】基于DeepSeek-R1与Qwen2.5Max的行业洞察自动化平台
自动生成行业报告,通过调用两个不同的大模型(DeepSeek 和 Qwen),完成从行业趋势分析到结构化报告生成的全过程。 完整代码:https://mp.weixin.qq.com/s/6pHi_aIDBcJKw1U61n1uUg 🧠 1. 整体目的与功能 该脚本实现了一个名为 ReportGenerator 的类,用于: 调用 DeepSe…...
UE5 关卡序列
文章目录 介绍创建一个关卡序列编辑动画添加一个物体编辑动画时间轴显示秒而不是帧时间轴跳转到一个确定的时间时间轴的显示范围更改关键帧的动画插值方式操作多个关键帧 播放动画 介绍 类似于Unity的Animation动画,可以用来录制场景中物体的动画 创建一个关卡序列…...
1.凸包、极点、极边基础概念
目录 1.凸包 2.调色问题 3.极性(Extrem) 4.凸组合(Convex Combination) 5.问题转化(Strategy)编辑 6.In-Triangle test 7.To-Left-test 8.极边(Extream Edges) 1.凸包 凸包就是上面蓝色皮筋围出来的范围 这些钉子可以转换到坐标轴中࿰…...
MahApps.Metro:专为 WPF 应用程序设计的 UI 框架
推荐一个WPF 应用程序设计的 UI 框架,方便我们快速构建美观、流畅的应用程序。 01 项目简介 MahApps.Metro 是一个开源的 UI 框架,它可以让开发者快速构建现代化、美观的 WPF 应用程序。 提供了一套完整的 UI 组件和主题,支持流畅的动画效…...
【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini,Spring Boot整合实战!| 附源码
【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini,Spring Boot整合实战! 前言:当Java遇上大模型 在AI浪潮席卷全球的今天,Java开发者如何快速拥抱大语言模型?LangChain4j作为专为Java打造的AI开发框架,…...
乐言科技:云原生加速电商行业赋能,云消息队列助力降本 37%
深耕 AI SaaS,助力数万电商客户数智化转型 上海乐言科技股份有限公司(以下简称“乐言科技”,官网:https://www.leyantech.com/)自 2016 年成立以来,专注于利用自然语言处理和深度学习等核心 AI 技术&#…...
vscode构建简单编译和调试环境
一、设置环境变量 将bin目录路径(如D:\DevTools\mingw64\bin)加入系统环境变量PATH34 二、VS Code插件配置 核心插件安装 C/C(微软官方扩展,提供语法高亮、智能提示)Code Runner࿰…...
STM32控制DRV8825驱动42BYGH34步进电机
最近想玩一下人工智能,然后买了个步进电机想玩一下,刚到了一脸懵逼,发现驱动器20多块,有点超预算,然后整了个驱动板,方便自己画线路板,经过各种搜索,终于转起来了,记录一…...
系统清理专家,一键释放磁盘空间!
打工人们你们好!这里是摸鱼 特供版~ 今天给大家带来一款超实用的系统清理工具——Glary Disk Cleaner,帮助你快速清理系统中的垃圾文件,释放磁盘空间,提升系统运行速度! 推荐指数:★★★★★ 软件简介 G…...
识别法院PDF文件特定字段并插入数据库【正则表达式+本地化部署】
pdf解析法院协助单特定字段,开源项目,结合若依项目进行开发,不连互联网,本地开发部署,前端使用vue3技术,后端用若依分离版spring botot技术,实现将pdf法院协助执行通知书中的特定字段如:时间、文…...
探索智能体开发新范式:Cangjie Magic深度解析与实践指南
引言:智能体开发的新纪元 2025年3月,仓颉社区开源了基于仓颉编程语言原生构建的LLM Agent开发平台——Cangjie Magic,为智能体开发领域带来了革命性的变革。作为一名长期关注AI技术发展的开发者,我有幸在第一时间体验了这一创新平…...
计算机网络 - UDP协议
通过一些问题来讨论 UDP 协议 什么是 UDP?举几个应用了 UDP 协议的例子UDP 与 TCP 有啥区别?(PS:介绍三四个就可以了,不用说太多)具体 UDP 是不可靠的,那你觉得如何实现一个可靠的 UDP &#x…...
阿里云ECS访问不了
使用xshell连接阿里云ECS,下载nginx,然后启动 sudo systemctl start nginx 查看状态是 sudo systemctl status nginx 输入公网ip访问实例访问不到,出现 可以查看阿里云实例中的安全组,是否对外开放了80端口和443端口 添加入方向…...
Starrocks添删改查数据(二)
先安装好Starrocks,参考:Starrocks入门(二)_backend node not found. check if any backend node -CSDN博客 1、建立库 建库成功。 2、建立表 参考:表概览 | StarRocks 执行如下SQL: CREATE TABLE user_…...
RT-Thread学习笔记(一)
RT-Thread学习笔记 AIotMMUCPU架构RT-Thread版本工程创建时钟配置FinSH内核RT-Thread内核启动流程 RT-Thread是一个组件完整丰富、高度可伸缩、简易开发、超低功耗、高安全性的物联网操作系统 全称Real Time Thread AIot AIot: Artificial Intelligence of Things…...
【源码】30个Python小游戏
下载链接:https://github.com/pyGuru123/Python-Games 本站下载链接:【免费】源码30个Python小游戏资源-CSDN文库 包含:飞机大战、愤怒的墙、圆弧冲刺、行星游戏、弹跳的球、汽车避障、洞穴物语、愤怒的小鸟、丛林探险、扫雷、俄罗斯方块、…...
【Web前端技术】第二节—HTML标签(上)
hello!好久不见—— 做出一个属于自己的网站! 云边有个稻草人-个人主页 Web前端技术—本篇文章所属专栏 目录 一、HTML 语法规范 1.1 基本语法概述 1.2 标签关系 二、HTML 基本结构标签 2.1 第一个 HTML 网页 2.2 基本结构标签总结 三、网页开发…...
Android开发协调布局滑动悬停
Android开发协调布局滑动悬停 直接给个xml,防止下次忘了怎么写。 <?xml version"1.0" encoding"utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android"http://schemas.android.com/apk/res/android…...
R语言简介与下载安装
1.R语言简介与下载安装 R语言其诞生于新西兰奥克兰大学,由Ross Ihaka 和Robert Gentleman开发,属于商业软件S语言的替代品;R语言是一款开源的编程类工具,专门用于数据清洗、整理、统计分析、可视化以及数据挖掘等方面,…...
CGAL边折叠edge_collapse的问题
使用edge_collapse对一个模型简化,之后回收垃圾,collect_garbage 处理之前的顶点和三角形数量: number_of_vertices: 955730 number_of_faces: 1903410 num_vertices: 955730 num_faces: 1903410 处理之后的顶点和三角形数量:…...
2025 全球分布式云大会演讲实录 | 沈建发:智启边缘,畅想未来:边缘计算新场景落地与 Al 趋势新畅想
4 月 9 日,2025 全球分布式云大会暨 AI 基础设施大会在深圳成功举办,火山引擎边缘云产品解决方案高级总监沈建发出席并以《智启边缘,畅想未来:边缘计算新场景落地与 Al 趋势新畅想》为主题,分享了边缘计算在 AI 技术趋…...
【ELF2学习板】OpenCL程序测试
目录 引言 OpenCL简介 主要特点 编程模型 应用场景 测试程序 代码说明 构建编译环境 头文件 库文件 程序编译 测试结果 结语 引言 ELF2开发板采用的是RK3588处理器,它是瑞芯微推出的一款高性能 SoC。RK3588 集成了 ARM Mali-G610 MP4 GPU,…...
EtherCAT转ProfiNet边缘计算网关配置优化:汽车制造场景下PLC与机器人协同作业案例
1.行业背景与需求分析 智能汽车焊装车间是汽车制造的核心工艺环节,某德国豪华品牌在其上海MEB工厂新建的焊装车间中,采用西门子S7-1500PLC作为ProfiNet主站,负责整线协调与质量追溯;同时部署KUKAKR1500Titan机器人(Eth…...
AI 推理与训练优化的核心理论体系建构及关键技术分析框架
AI 推理与训练优化的核心理论体系建构及关键技术分析框架 一、推理加速的动态系统理论建模与算法设计 (一)基于MDP的动态计算图理论 生物启发的决策框架:模拟灵长类视觉系统的注意力分配机制,构建马尔可夫决策过程(M…...
Jupyter 中 Markdown 邂逅 LaTeX:一场知识的绮梦
引言: 在日常编程和数据分析工作中,我们经常需要记录和分享信息。传统的注释方式功能有限,而富文本编辑器又过于臃肿。Markdown作为一种轻量级标记语言,完美解决了这个问题。 为什么选择Markdown? Markdown具有两大优势…...
AI 对话高效输入指令攻略(二):关于豆包的指令
免责声明:该文章的所有样例只是测试,没有唆使大家利用AI抄袭作业!更没有宣传豆包。 前言 没有听不懂话的AI,只有不会调教AI的人。(自己瞎说的)当你把AI当人看之后,你就会发现,他是多…...
Apache Atlas构建安装(Linux)
一、环境准备 maven 3.6.3python 2.7nodejs 12java 1.8 注意环境一定要对,不然一堆问题 1. python2.7 安装 参考文章:https://blog.csdn.net/weixin_42081389/article/details/101276251 打开链接:https://www.python.org/downloads/sourc…...
【JAVA】在idea新加artifact时,点击Build-Build Artifacts时,新加的artifact不能选中
首先保证添加artifact无问题,比如依赖都正确、无重复命令的情况等 办法 一 File > Invalidate Caches / Restart。 重启IDEA后,重新检查Artifact是否可选 办法 二 打开 Project Structure(CtrlShiftAltS)。 进入 Artifacts 选…...