Flutter学习总结之Android渲染对比
一、Android 界面渲染机制(基于原生 View 体系)
1. 核心渲染流程(源码级解析)
-
三阶段渲染流程(
ViewRootImpl
驱动):- Measure 阶段(
measure()
):
View
调用onMeasure()
计算自身宽高,父容器通过MeasureSpec
约束子 View 尺寸,最终生成MeasuredDimension
。
关键类:View
、ViewGroup
、MeasureSpec
。 - Layout 阶段(
layout()
):
父容器通过onLayout()
确定子 View 的位置(left/top/right/bottom
),递归遍历整个 View 树。
核心逻辑:ViewGroup
的layoutChildren()
(如LinearLayout
的垂直布局、RelativeLayout
的依赖布局)。 - Draw 阶段(
draw()
):
调用onDraw()
绘制内容,包括背景、边框、文字、图形等,最终通过Canvas
渲染到屏幕。
优化点:硬件加速(setLayerType(HARDWARE, null)
)将绘制任务交给 GPU,减少 CPU 负载。
- Measure 阶段(
-
VSYNC 同步与 Choreographer:
Android 通过Choreographer
监听屏幕 VSYNC 信号(60Hz 约 16ms / 帧),在doFrame()
中触发performTraversals()
,协调measure/layout/draw
流程,确保流畅动画。
源码入口:ViewRootImpl#scheduleTraversals()
→Choreographer#postCallback()
。 -
SurfaceFlinger 合成:
各窗口的Surface
通过SurfaceFlinger
合成到屏幕,最终通过 GPU 的RenderThread
完成栅格化(Rasterization)。
2. 渲染特点
- 依赖系统图形服务:依赖 Android 框架的
WindowManager
、Surface
、Skia
(系统级库)。 - UI 线程唯一性:
measure/layout/draw
必须在主线程(UI 线程)执行,跨线程操作需通过runOnUiThread()
。 - View 层级深度影响性能:嵌套层级过深会导致多次遍历,触发
Overdraw
(过度绘制)。
二、Flutter 界面渲染机制(自包含引擎架构)
1. 核心渲染流程(Dart→Engine→GPU)
-
Widget 树→Element 树→Render 树:
- Widget 构建(Dart 层):
通过build()
生成不可变的Widget
描述,对应可变的Element
实例(记录状态)。
关键类:StatelessWidget
/StatefulWidget
、Element
、BuildContext
。 - 布局与绘制(Render 层):
RenderObject
树执行布局(performLayout()
)和绘制(paint()
),通过PipelineOwner
管理渲染流程。
核心逻辑:RenderBox
(处理盒模型布局)、RenderParagraph
(文本渲染)、Canvas
(Skia 封装)。 - 引擎层渲染:
Dart 层通过PlatformView
或Texture
将渲染指令发送到 Flutter 引擎(C++ 实现),引擎调用 Skia 库将RenderObject
绘制到Scene
,最终通过 GPU 合成器(如 Android 的AndroidContext
或 iOS 的Metal
)渲染到屏幕。
- Widget 构建(Dart 层):
-
线程模型:
- UI 线程(Dart):处理
Widget
构建、布局、绘制指令生成。 - GPU 线程(引擎层):独立于 UI 线程,执行 Skia 渲染和 GPU 合成,避免 UI 线程阻塞。
- IO 线程:处理异步任务(如网络、文件)。
- UI 线程(Dart):处理
-
分层渲染与合成:
Flutter 将不同层级的内容(如文本、图片、动画)拆分为Layer
,通过SceneBuilder
合并为Scene
,引擎层批量提交到 GPU,减少渲染指令次数。
三、核心区别对比(面试官高频问题解析)
对比维度 | Android 原生渲染 | Flutter 渲染 |
---|---|---|
渲染架构 | 依赖系统 View 体系,通过WindowManager /SurfaceFlinger | 自包含引擎(Flutter Engine),内置 Skia,不依赖原生 View |
UI 更新机制 | invalidate() 触发重绘,需手动管理 View 状态 | 状态变化触发Widget 重建,通过Element diff 算法高效更新 |
线程模型 | 单 UI 线程(主线程)执行渲染逻辑 | UI 线程(Dart)生成渲染指令,GPU 线程独立执行渲染 |
渲染引擎 | 系统级 Skia(Android Framework 自带) | 内置 Skia(Flutter 定制版本),跨平台统一实现 |
自定义能力 | 需继承View /ViewGroup ,重写onDraw() 等方法 | 通过CustomPainter 直接操作 Skia Canvas,自由度更高 |
性能优化点 | 减少布局层级、避免 Overdraw、硬件加速 | 减少 Widget 重建、层合并(Layer)、GPU 线程并行渲染 |
跨平台实现 | 依赖各平台原生控件,需双端适配 | 自绘所有 UI 元素,一套代码编译为双端二进制,真正 “一次编写,到处运行” |
启动速度 | 首次渲染需加载系统 View 库,启动时间受限于 Java 反射 | Dart JIT/AOT 编译,引擎启动后渲染速度接近 |
四、面试官高频问题回答示例
问题 1:“Flutter 为什么能实现高性能渲染?”
回答:
Flutter 的高性能源于三大设计:
- 自包含引擎与 Skia 直接渲染:跳过原生 View 的跨语言调用开销(如 Java→C++),Dart 层直接生成渲染指令,引擎层通过 Skia 高效绘制。
- GPU 线程独立渲染:UI 构建(Dart)与 GPU 渲染(引擎层)在不同线程并行处理,避免主线程阻塞,例如滑动列表时 UI 线程可同时处理新帧构建。
- 分层合成与批量提交:将界面拆分为
Layer
,通过SceneBuilder
合并后一次性提交到 GPU,减少渲染指令次数,降低 GPU 负载。
问题 2:“Android 原生渲染中,如何避免主线程阻塞?”
回答:过度绘制源于多层重叠的无效绘制,常见场景:
- 多层不透明背景叠加(如 Activity 窗口默认背景 + 布局背景 + 控件背景);
- 未使用
clipRect()
限制绘制区域。
优化手段: - 通过开发者选项开启 “显示过度绘制区域”,定位红色 / 蓝色区域(红色为过度绘制 4 次以上);
- 简化布局背景,使用
android:background="@null"
移除冗余背景; - 对复杂绘制区域调用
canvas.clipRect()
限制绘制范围; - 启用硬件加速(
android:hardwareAccelerated="true"
),利用 GPU 缓存提升合成效率。
问题 3:“Flutter 如何实现跨平台 UI 的一致性?”
回答:Flutter 不依赖任何平台的原生控件,所有 UI 元素(按钮、文本、动画)均通过内置 Skia 引擎自绘。
例如:
- 文本渲染使用
RenderParagraph
直接调用 Skia 的文本绘制接口,避免 Android 的TextView
与 iOS 的UILabel
的字体渲染差异; - 布局计算基于统一的盒模型(
RenderBox
),消除不同平台布局引擎的实现差异。
因此,相同的 Dart 代码在编译为 Android APK 或 iOS 二进制文件后,会生成完全一致的渲染指令,实现真正的 “一次编写,到处运行”。
总结
- Android 原生渲染:适合深度系统交互(如自定义窗口动画、硬件传感器融合界面),但需重点优化布局层级(推荐
ConstraintLayout
)和避免 UI 线程阻塞。 - Flutter 渲染:适合跨平台快速开发(尤其是电商、社交类应用),其自包含引擎和 Skia 直接渲染能力,在复杂动效和高帧率场景下表现优异,但需注意
Widget
重建性能(避免在build
方法中执行耗时操作)。
感谢观看!!!
相关文章:
Flutter学习总结之Android渲染对比
一、Android 界面渲染机制(基于原生 View 体系) 1. 核心渲染流程(源码级解析) 三阶段渲染流程(ViewRootImpl驱动): Measure 阶段(measure()): View调用onMea…...
Media streaming mental map
Media streaming is a huge topic with a bunch of scattered technologies, protocols, and formats. You may feel like hearing fragments without seeing the big picture. Let’s build that mental map together — here’s a high-level overview that connects everyt…...
7B斗671B:扩散模型能否颠覆自回归霸权?
模型对决:从7B到671B的意外之战 参数量与性能的反差 DeepSeek V3以6710亿参数稳坐自回归模型的“巨无霸”地位,而70亿参数的Dream 7B却在多项测试中与其不分伯仲。例如,在需要复杂规划的“倒计时任务”中,Dream 7B的解题成功率比…...
WVP-GB28181摄像头管理平台存在弱口令
免责声明:本号提供的网络安全信息仅供参考,不构成专业建议。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我联系,我将尽快处理并删除相关内容。 漏洞描述 攻击者可利用漏洞获取当前系统管…...
实验研究:不同物体与落点材质对弹起高度的影响
本研究通过控制变量法,探讨了不同物体(乒乓球和笔)在不同下落高度和落点材质条件下,其弹起高度的变化。实验结果显示,物体类型、下落高度和落点材质均对弹起高度有显著影响。其中,铁碗作为落点材质时&#…...
开源 PDF.js 文件编辑操作
一、PDF.js PDF.js 是 Mozilla 基金会推出的一个使用 HTML5 构建的 PDF 阅读器,它完全使用 JavaScript 编写。作为 Firefox 浏览器的默认 PDF 查看器,PDF.js 具有强大的兼容性和稳定性。它不仅支持 PDF 文件的查看和渲染,还提供了丰富的交互…...
hydra小记(一):深入理解 Hydra:instantiate() 与 get_class() 的区别
hydra小记(一):深入理解 Hydra:instantiate 与 get_class 的区别 深入理解 Hydra:instantiate() 与 get_class() 的区别1. hydra.utils.get_class()2. hydra.utils.instantiate()3. 总结对比 深入理解 Hydra࿱…...
在 macOS 上安装和配置 Aria2 的详细步骤
在 macOS 上安装和配置 Aria2 的详细步骤: 1.安装 Aria2 方式一:使用 Homebrew Homebrew 是 macOS 上的包管理器,可以方便地安装和管理软件包。 • 打开终端。 • 输入以下命令安装 Aria2: brew install aria2• 检查安装是否…...
Linux开发工具——make/makefile
📝前言: 这篇文章我们来讲讲Linux开发工具——make/makefile: 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀CSDN主页 愚润求学 🌄其他专栏:C学习笔记…...
生信分析服务MR孟德尔随机化单细胞测序转录组数据分析网络药理学
将孟德尔随机化(MR)、单细胞测序、转录组数据分析和网络药理学结合,是当前生物信息学领域的前沿方法,尤其在疾病机制解析、靶点发现和药物研发中展现出巨大潜力。以下从技术逻辑、应用场景和服务流程三个维度展开说明:…...
Sentinel实战(五)、系统保护规则、限流后统一处理及sentinel持久化配置
Spring Cloud Alibaba-Sentinel实战(五)、系统保护规则、限流后统一处理及sentinel持久化配置 一、系统保护规则一)、系统规则支持的模式二)、新增系统规则界面三)、demo测试二、限流后统一处理实操demo三、sentinel持久化配一、系统保护规则 系统保护规则是从应用级别的…...
iPhone XR:一代神机,止步于此
什么样的 iPhone ,才配称为一代神机? 我曾经用过iPhone 4S、iPhone 6S Plus、iPhone 8 Plus,iPhone SE2、iPhone XR、iPhone 13、iPhone 14 Plus、iPhone 15/Pro。 不管硬件再怎么卷,不管囊中是否羞涩,主力机基本没考…...
[C++面试] explicit面试8问 —— 较难,可简单了解即可
Google C规范建议所有单参数构造函数必须加explicit,除非明确需要隐式转换(如std::string从const char*构造)。 1. 隐式转换的实际危害 隐式转换可能导致资源泄漏或逻辑错误(如std::vector<int> v 10;可能被误认为初始化…...
2024-2025 CSS前沿技术全景解析:构建下一代Web界面的核心武器库
前言:CSS的范式革命 当WebAssembly与JavaScript持续争夺开发者注意力时,CSS正在经历一场静默的革命。2024年CSS工作组发布的Level 4/5草案,标志着样式语言正式进入「智能样式」时代。本文将从15个维度深入剖析未来两年最具变革性的CSS新特性…...
flutter row里面怎么统一高度
在 Flutter 中,Row 是一个水平布局的组件,默认情况下,它的子组件的高度是根据每个子组件的内容自动调整的。如果你希望 Row 中的所有子组件具有统一的高度,可以通过以下几种方式实现。 1. 使用 SizedBox 或 Container 设置固定高度…...
pinia-plugin-persist、vuex
pinia-plugin-persist 作用:为 Pinia 状态管理库实现状态持久化,自动将指定的 Pinia store 状态保存到本地存储(如 localStorage 或 sessionStorage),并在应用启动时从本地存储恢复状态。效果:确保应用状态…...
Spring Boot整合MyBatis-Plus实现CRUD操作教程
本文将演示如何在Spring Boot项目中整合MyBatis-Plus框架,快速实现数据库的增删改查操作。相较于原生MyBatis,MyBatis-Plus提供了更简洁的API和自动化功能。 环境准备 JDK 1.8MySQL 5.7Spring Boot 2.7.xMyBatis-Plus 3.5.x 实现步骤 1. 创建项目并添加…...
Vue 3 的响应式原理
Vue 3 的响应式原理可以比喻为“智能监控系统”:当数据变化时,它能自动追踪依赖关系并触发更新。以下是通俗解释和核心机制: 一、核心原理:Proxy 代理 Vue 3 的响应式系统基于 JavaScript 的 Proxy 对象实现(Vue 2 使…...
使用Scrapy官方开发的爬虫部署、运行、管理工具:Scrapyd
一般情况下,爬虫会使用云服务器来运行,这样可以保证爬虫24h不间断运行。但是如何把爬虫放到云服务器上面去呢?有人说用FTP,有人说用Git,有人说用Docker。但是它们都有很多问题。 FTP:使用FTP来上传…...
基于51单片机和8X8点阵屏、独立按键的单人弹球小游戏
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 用的是普中A2开发板,用到板上的独立按键、8X8点阵屏。 【单片机】STC89C52RC 【频率】12T11.0592MHz 效果查看/操作…...
群体智能避障革命:RVO算法在Unity中的深度实践与优化
引言:游戏群体移动的挑战与进化 在《全面战争》中万人战场恢弘列阵,在《刺客信条》闹市里人群自然涌动,这些令人惊叹的场景背后,都离不开一个关键技术——群体动态避障。传统路径规划算法(如A*)虽能解决单…...
Java 实现选择排序:[通俗易懂的排序算法系列之一]
引言 大家好!从今天开始,我计划写一个关于常见排序算法的系列文章,旨在用通俗易懂的方式,结合 Java 代码实现,帮助大家理解和掌握这些基础但非常重要的数据结构与算法知识。 排序是计算机科学中最基本的操作之一&…...
动画过渡设置
使用Animator的Trigger参数 步骤 1:打开 Animator 窗口 确保你的 Sprite 对象已添加 Animator 组件。 在 Unity 编辑器顶部菜单栏,选择 Window > Animation > Animator,打开 Animator 窗口。 步骤 2:创建 Trigger 参数 在…...
【项目管理-高项】学习方法 整体概览
相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 📝 软考高项,全称 信息系统项目管理师 ,是软考高级资格项目之一。 本考试考三门科目:综合知识(上午)、案例分析(下午…...
HarmonyOS应用开发者高级-编程题-001
题目一:跨设备分布式数据同步 需求描述 开发一个分布式待办事项应用,要求: 手机与平板登录同一华为账号时,自动同步任务列表任一设备修改任务状态(完成/删除),另一设备实时更新任务数据在设备…...
HarmonyOS-ArkUI Ability进阶系列-UIAbility与各类Context
UIAbility及相关类关系 一个模块编译的时候会出一个HAP包, 每一个HAP包在运行时都对应一个AbilityStage。 AbilityStage持有一个AbilityStageContext一个APP, 有时候会有很多个HAP包, 至少一个。 一个APP运行时,对应的是我们的App…...
接口并行执行且流式顺序输出的解决方案
接口并行执行且流式顺序输出的解决方案: import asyncio from aiotas_agi2all_llms_utils.output_answer_from_ask_question_results import (reasoning_model_ask_question, ) import os from aiotas_agi2all_llms_utils.logging_utils import create_logger import uuid fr…...
浅谈AI - DeepSpeed - 单卡慎用!
前言 曾在游戏世界挥洒创意,也曾在前端和后端的浪潮间穿梭,如今,而立的我仰望AI的璀璨星空,心潮澎湃,步履不停!愿你我皆乘风破浪,逐梦星辰! 简介 Deepspeed 的 ZeRO(Ze…...
Java Web从入门到精通:全面探索与实战(一)
目录 引言:开启 Java Web 之旅 一、Java Web 基础概念大揭秘 1.1 什么是 Java Web 1.2 Java Web 的优势剖析 1.3 Java Web 相关核心概念详解 二、搭建 Java Web 开发环境:步步为营 2.1 所需软件大盘点 2.2 软件安装与配置全流程 三…...
5G从专家到小白
文章目录 第五代移动通信技术(5G)简介应用场景 数据传输率带宽频段频段 VS 带宽中低频(6 GHz以下):覆盖范围广、穿透力强高频(24 GHz以上):满足在热点区域提升容量的需求毫米波热点区…...
leetcode111 二叉树的最小深度
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。 最小深度的定义:从根节点到最近叶子节点的最短路径上的节点数量。 特别注意: 如果一个子树不存在,就不能用它来计算深度&#x…...
算法设计学习10
实验目的及要求: 本查找实验旨在使学生深入了解不同查找算法的原理、性能特征和适用场景,培养其在实际问题中选择和应用查找算法的能力。通过实验,学生将具体实现多种查找算法,并通过性能测试验证其在不同数据集上的表现ÿ…...
数字统计题解
题目理解 题目要求计算所有不大于 N 的非负整数中数字 D 出现的总次数。例如,当 D1 且 N12 时,数字1出现在1、10、11(两次)、12中,共5次。 输入输出分析 输入格式: 两个正整数 D 和 N,其中1≤…...
eclipse导入工程提示Project has no explicit encoding set
eclipse导入工程提示Project has no explicit encoding set-CSDN博客...
【网络安全论文】筑牢局域网安全防线:策略、技术与实战分析
【网络安全论文】筑牢局域网安全防线:策略、技术与实战分析 简述一、引言1.1 研究背景1.2 研究目的与意义1.3 国内外研究现状1.4 研究方法与创新点二、局域网网络安全基础理论2.1 局域网概述2.1.1 局域网的定义与特点2.1.2 局域网的常见拓扑结构2.2 网络安全基本概念2.2.1 网络…...
JVM虚拟机篇(五):深入理解Java类加载器与类加载机制
深入理解Java类加载器与类加载机制 深入理解Java类加载器与类加载机制一、引言二、类加载器2.1 类加载器的定义2.2 类加载器的分类2.2.1 启动类加载器(Bootstrap ClassLoader)2.2.2 扩展类加载器(Extension ClassLoader)2.2.3 应用…...
纯个人整理,蓝桥杯使用的算法模板day4(图论 最小生成树问题),手打个人理解注释,超全面,且均已验证成功(附带详细手写“模拟流程图”,全网首个
目录 最小生成树Prim代码模拟流程图 kruskal代码 代码对应实现案例 最小生成树 最小生成树:在无向图中求一棵树(n-1条边,无环,连通所有点),而且这棵树的边权和最小 (ps:可能结果不止…...
学习笔记,DbContext context 对象是保存了所有用户对象吗
DbContext 并不会将所有用户对象保存在内存中: DbContext 是 Entity Framework Core (EF Core) 的数据库上下文,它是一个数据库访问的抽象层它实际上是与数据库的一个连接会话,而不是数据的内存缓存当您通过 _context.Users 查询数据时&…...
Kafka 和 Flink的讲解
一、Kafka:分布式消息队列 1. 核心概念 角色:Kafka 是一个分布式、高吞吐量的消息队列(Pub-Sub 模型),用于实时传输数据流。关键术语: Producer(生产者&…...
Kafka 高吞吐量的原因是什么?
Kafka 的高吞吐量是它成为“数据中枢”的关键特性之一,这背后是多个技术设计的巧妙配合。下面我给你整理一下 Kafka 高吞吐量的主要原因,通俗又系统。 ✅ 1. 顺序写磁盘(磁盘也能飞) Kafka 的消息写入是追加到日志末尾ÿ…...
基于Python+Flask的服装零售商城APP方案,用到了DeepSeek AI、个性化推荐和AR虚拟试衣功能
首先创建项目结构: fashion_store/ ├── backend/ │ ├── app/ │ │ ├── __init__.py │ │ ├── models/ │ │ ├── routes/ │ │ ├── services/ │ │ └── utils/ │ ├── config.py │ ├── requirements.t…...
26.[MRCTF2020]Transform 1
打开文件是可执行程序.exe,打开看一下,顺便拖入ExeinfoPE 查询一下基本信息。如图。 无壳,且是64-bit,打开执行文件也没有什么特别的信息。那就 IDA-x64 分析吧。 🆗,简单的一个加密,我们直接逆…...
LeetCode-98. 验证二叉搜索树
一、题目 给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的…...
【LeetCode Solutions】LeetCode 146 ~ 150 题解
CONTENTS LeetCode 146. LRU 缓存(中等)LeetCode 147. 对链表进行插入排序(中等)LeetCode 148. 排序链表(中等)LeetCode 149. 直线上最多的点数(困难)LeetCode 150. 逆波兰表达式求值…...
leetcode二叉树刷题调试不方便的解决办法
1. 二叉树不易构建 在leetcode中刷题时,如果没有会员就需要将代码拷贝到本地的编译器进行调试。但是leetcode中有一类题可谓是毒瘤,那就是二叉树的题。 要调试二叉树有关的题需要根据测试用例给出的前序遍历,自己构建一个二叉树,…...
【家政平台开发(16)】消息通知系统设计:搭建高效沟通桥梁
本【家政平台开发】专栏聚焦家政平台从 0 到 1 的全流程打造。从前期需求分析,剖析家政行业现状、挖掘用户需求与梳理功能要点,到系统设计阶段的架构选型、数据库构建,再到开发阶段各模块逐一实现。涵盖移动与 PC 端设计、接口开发及性能优化…...
AI比人脑更强,因为被植入思维模型【44】成长破圈思维
giszz的理解:芒格说,不懂不投。我们一生都在追求破圈,突破本我,突破舒适圈、恐惧圈、学习圈、成长圈、自在圈,可是我们真正能懂的知识有实际真的太少了。这个思维模型给我的启迪,一是要破圈,二是…...
【JavaWeb-Spring boot】学习笔记
目录 <<回到导览Spring boot1. http协议1.1.请求协议1.2.响应协议 2.Tomcat2.1.请求2.1.1.apifox2.1.2.简单参数2.1.3.实体参数2.1.4.数组集合参数2.1.5.日期参数2.1.6.(重点)JSON参数2.1.7.路径参数 2.2.响应2.3.综合练习 3.三层架构3.1.三层拆分3.2.分层解耦3.3.补充 &…...
基于GitLab+Jenkins的持续集成实践指南
架构设计原则 分层自动化策略 基础层: 代码提交触发自动构建(100%自动化)中间层: 制品生成与验证(自动化+人工审核)发布层: 环境部署(受控手动触发)工具定位矩阵 工具核心职责关键优势GitLab源码管理+MR流程精细的权限控制Jenkins流水线编排+任务调度插件生态丰富Nexus制…...
用HTML.CSS.JavaScript实现一个贪吃蛇小游戏
目录 一、引言二、实现思路1. HTML 结构2. CSS 样式3. JavaScript 逻辑 三、代码实现四、效果展示 一、引言 贪吃蛇是一款经典的小游戏,曾经风靡一时。今天,我们将使用 HTML、CSS 和 JavaScript 来实现一个简单的贪吃蛇小游戏。通过这个项目,…...