面试
Flutter面试题2
渲染管线、引擎线程、Channel、卡顿、混合栈与启动体积。
和 高频面试题 1 重叠的概念,这里只写引擎 / 工程视角。
一帧怎么上屏
- 三棵树: Widget 是配置,Element 是实例,RenderObject 做布局和绘制指令。
- 一帧: build → layout → paint(只记指令)→ composite → raster 上屏。
- 和原生差别: Flutter 默认自绘。PlatformView 是例外。
| 布局 / 绘制 | 合成 / GPU | |
|---|---|---|
| 对应 | DevTools UI 条 | Raster 条 |
| 贵在 | 树深、build 范围大 | saveLayer、大图、离屏 |
面试点:Widget → Element → RenderObject → Layer → GPU。
paint 不等于已经上屏。vsync 和 SchedulerBinding
- vsync: 对齐刷新。60Hz 约 16.6ms,超时掉帧。
- 调度: 动画用
Ticker;画帧走drawFrame;量尺寸用addPostFrameCallback。 - 别用
Timer做动画: 对不齐刷新。跟的是屏,类似CADisplayLink/Choreographer。
面试点:不要在
build 里量 size,用 LayoutBuilder 或帧后再读。UI Isolate 和引擎线程
- UI Isolate: Widget、
setState、业务、Channel 的 Dart 回调 - Platform: Activity / AppDelegate、plugin
- IO: 网络、部分解码
- Raster: Layer → 像素(旧称 GPU 线程)
Isolate.run 是再开一个 Dart 堆,不是 Raster。DevTools:UI 条长查 Dart,Raster 条长查绘制。
面试点:卡 UI 和卡 GPU 不是同一根条。
三种 Channel
| MethodChannel | EventChannel | BasicMessageChannel | |
|---|---|---|---|
| 语义 | 一次问一次答 | 持续推流 | 双向消息 |
| 典型 | 支付、权限 | 传感器 | 自定义协议 |
Pigeon 不是第四种通道,只是给 Method 这类 RPC 生成类型。大图传路径或纹理 id,别传像素。
面试点:先选语义,再说 codec。都要过主线程和序列化。
卡顿怎么分层
先看 DevTools 的 UI 条和 Raster 条,没分层不谈优化。
- UI 长:
setState太高、列表没builder、layout 太深、Intrinsic* - Raster 长:
Opacity、裁剪、阴影、saveLayer、超大图 RepaintBoundary: 重绘确实局部才加,不是万能的
面试点:profile 下看。FPS 是平均数,jank 是单帧超没超预算。
热重载保什么
定义见 高频面试题 1。这里只记状态。
- 能保: 改
build、改方法体。runtimeType+ Key 对得上就复用State。 - 保不住:
initState/main/static、类型变化、原生代码。 - 改了没变: 先怀疑旧 State,不是框架坏了。
| 热重载 | 热重启 | |
|---|---|---|
| 状态 | 尽量保 Element / State | 清空,重跑 main() |
| 何时 | UI、方法体 | 入口、类型、全局 |
面试点:
initState 不重走,改初始化必须热重启。PlatformView
原生视图嵌进 Flutter,合成更贵。WebView、地图、播放器才值得嵌。
- 页面级(FlutterBoost):整页是 Flutter 还是原生
- 组件级(PlatformView):一页里嵌一块
- 坑: 手势、圆角、透明 → 花屏、穿透
能用 Flutter 画的就不要嵌。别把混合栈和 PlatformView 说成一件事。
启动慢、包体积大
两条线,别混。
- 启动: 先问慢在闪屏、首帧,还是首屏数据。别等网络才
runApp。 - 体积: 先问是 debug 还是 release、几个 ABI。只比 release。
| 启动 | 体积 | |
|---|---|---|
| 先砍 | 过早初始化、首屏等网络 | 多 ABI、原图、全量字体、符号 |
面试点:冷 / 热启动分开说。Debug 包不进对比。