跨平台方案 — 面试题篇
更新: 5/15/2026 字数: 0 字 时长: 0 分钟
Q1: Flutter 的渲染原理?和 Android 原生有什么区别?
考察点:Flutter 架构理解
完整回答:
Flutter 不使用原生控件,通过 Skia(新版用 Impeller)自绘 UI。
Flutter 维护三棵树:
- Widget 树:不可变的配置描述,类似声明式 UI 的蓝图
- Element 树:Widget 的实例化,管理生命周期,决定是否复用
- RenderObject 树:负责实际的布局(layout)和绘制(draw)
渲染流程:Widget 变化 → Element 对比新旧 Widget(canUpdate:类型+key 相同则复用)→ 更新 RenderObject → Skia 绘制 → GPU 渲染
和 Android 原生的区别:
- Android 原生:View 系统,每个控件是平台原生组件,通过 Canvas 绑制
- Flutter:完全自绘,不依赖平台控件,所以跨平台 UI 完全一致
- 性能:Flutter 自绘接近原生,但首次启动需要加载 Dart VM 和 Flutter Engine
追问:Flutter 的 Widget 重建开销大吗?
Widget 是轻量的不可变对象,重建开销很小。真正的开销在 RenderObject 的布局和绘制。Element 层通过 canUpdate 机制复用 RenderObject,避免不必要的重建。类似 Compose 的重组跳过机制。
Q2: Flutter 和 Native 怎么通信?
考察点:混合开发能力
完整回答:
通过 Platform Channel 通信,三种类型:
MethodChannel:方法调用,一次请求一次响应。最常用,如获取电量、调用原生相机。
EventChannel:事件流,Native 持续向 Dart 发送数据。如传感器数据、位置更新。
BasicMessageChannel:自定义编解码的消息传递。
通信是异步的,数据通过标准编解码器序列化(StandardMessageCodec 支持基本类型、List、Map)。
追问:混合开发中页面栈怎么管理?
Flutter 和 Native 各有独立的页面栈。混合导航的挑战是两个栈的同步。解决方案:
- flutter_boost:统一管理 Flutter 和 Native 页面栈,每个 Flutter 页面对应一个 Native 容器
- 单 Engine 多页面:共享一个 FlutterEngine,通过路由管理 Flutter 内部页面
追问:FlutterEngine 的预热是什么?
FlutterEngine 创建时需要初始化 Dart VM、加载 Dart 代码,耗时约 200-500ms。预热是在 Application 中提前创建 Engine 并缓存,用户打开 Flutter 页面时直接复用,避免等待。
Q3: KMM 的 expect/actual 机制是什么?
考察点:KMM 原理
完整回答:
KMM 通过 expect/actual 实现跨平台:
expect:在 commonMain 中声明接口(期望)actual:在各平台模块中提供具体实现
// commonMain
expect fun platformName(): String
// androidMain
actual fun platformName(): String = "Android ${Build.VERSION.SDK_INT}"
// iosMain
actual fun platformName(): String = UIDevice.currentDevice.systemName()编译时,Kotlin 编译器检查每个 expect 声明都有对应的 actual 实现。
适合共享的:网络层(Ktor)、数据库(SQLDelight)、业务逻辑、数据模型。 不适合共享的:UI、平台特定 API。
追问:KMM 和 Flutter 怎么选?
- KMM:只共享逻辑层,UI 保持原生。适合已有成熟原生 App,想逐步共享业务逻辑。Android 开发者学习成本低(就是 Kotlin)。
- Flutter:共享 UI + 逻辑。适合新项目,追求开发效率和 UI 一致性。需要学习 Dart。
Q4: 跨平台方案怎么选型?
考察点:技术选型能力
完整回答:
选型维度:
| 维度 | Flutter | KMM | React Native |
|---|---|---|---|
| 共享范围 | UI + 逻辑 | 仅逻辑 | UI + 逻辑 |
| 性能 | 接近原生(自绘) | 原生 | 略低(JS 桥接) |
| UI 体验 | 跨平台一致 | 原生 UI | 跟随平台 |
| 热更新 | 不支持 | 不支持 | 支持(CodePush) |
| 团队 | 需要 Dart 开发者 | Kotlin 开发者 | 前端开发者 |
选型建议:
- 新项目 + UI 一致性 → Flutter
- 已有原生 App + 共享逻辑 → KMM
- 前端团队 + 热更新需求 → React Native
- 核心体验页面 → 保持原生
实际项目中,很多大厂采用混合方案:核心页面原生,非核心页面 Flutter/RN,业务逻辑 KMM 共享。
Q5: Flutter 的状态管理方案有哪些?
考察点:Flutter 开发实践
完整回答:
- setState:最基础,适合简单组件内部状态
- Provider:官方推荐的轻量级方案,基于 InheritedWidget
- Riverpod:Provider 的改进版,编译期安全,不依赖 BuildContext
- Bloc:基于事件驱动的状态管理,类似 MVI。Event → Bloc → State
- GetX:全家桶方案,包含状态管理、路由、依赖注入。简单但不够规范
选择建议:
- 小项目:Provider 或 Riverpod
- 大项目:Bloc(规范性强)或 Riverpod
- 快速原型:GetX
加分点:对比 Flutter 的 Bloc 和 Android 的 MVI,思想类似——都是单向数据流,Event/Intent → 处理 → State → UI。
实习面试补充:跨平台了解型问题
对 Android 实习生来说,Flutter/KMM 通常是加分项。重点是知道它们解决什么问题、和原生开发有什么区别。
Q6: Flutter 和原生 Android 开发有什么区别?
考察点:跨平台基础认知
完整回答:
Flutter 使用 Dart 编写 UI 和业务逻辑,通过自己的渲染引擎绘制界面,可以一套代码运行在 Android、iOS 等平台。原生 Android 使用 Kotlin/Java,直接使用 Android 系统提供的 View、Activity、Fragment、Jetpack 等能力。
区别:
- Flutter 跨平台效率高,UI 一致性强。
- 原生 Android 对平台能力、系统 API 和性能细节控制更直接。
- Flutter 访问相机、定位、蓝牙等平台能力时,需要通过插件或 Platform Channel 调用原生代码。
加分点:如果团队主要追求多端一致 UI 和快速迭代,Flutter 有优势;如果需要深度使用 Android 系统能力,原生更稳。
Q7: KMM 主要共享什么?和 Flutter 最大区别是什么?
考察点:Kotlin Multiplatform 基础
完整回答:
KMM 通常共享业务逻辑、数据层、网络层、算法和工具代码,Android 和 iOS 仍然分别使用各自原生 UI。
和 Flutter 的最大区别:
- Flutter 倾向于 UI 和业务都跨平台。
- KMM 倾向于共享非 UI 逻辑,UI 仍然保持原生。
因此 KMM 更适合希望保留原生体验,同时减少业务逻辑重复开发的团队。
