Skip to content

Android 架构总览:分层、线程模型、组件系统与 UI 范式 ​

模块位置:并发与运行时底座 README
相关主题:Android 主线程消息循环:Looper / Handler / MessageQueue · Android Binder IPC 机制与跨进程通信 · Android ANR 触发机制、排障定位与防范 · Android 生命周期总览 · ViewModel 架构、SavedStateHandle 与进程被杀恢复 · Jetpack Compose 状态模型、StateFlow 与重组优化 · Android App 进程启动全流程

一句话定义 ​

Android 不是“一个 Java UI SDK”,而是一个由 Linux Kernel / 系统服务 / Native 库 / Android Runtime / Framework API / 应用组件 逐层叠起来的平台:线程、消息循环、Binder、生命周期、View/Compose、WebView、Flutter 宿主都只是这张大图里的不同切面。

为什么需要 ​

如果只按 Activity、Handler、ViewModel、Compose、Flutter Plugin 这些局部知识点工作,平时能写业务,但一旦进入下面这些问题,判断会开始飘:

  • Android 整个平台到底是怎样分层的,app_process、Framework、ART、Native、Kernel 各自负责什么?
    • 一句话答:Kernel 提供调度/驱动/进程隔离,Native 提供 Binder/图形/媒体等系统能力,ART 承载 Java/Kotlin 代码执行,Framework 把系统服务包装成应用 API,App 层再用组件模型把页面、服务、广播和内容提供者组织起来。
  • 线程、消息循环、组件生命周期在这张图里分别属于哪一层?
    • 一句话答:线程与消息循环属于“运行时执行机制”,组件生命周期属于“Framework 对应用组件的调度契约”,二者在主线程上交汇成 Activity/Service/BroadcastReceiver 的真实执行现场。
  • 为什么 Android 既能跑 Java/Kotlin,又能承载 JNI/NDK、WebView、Flutter、游戏引擎?
    • 一句话答:因为 Android 在 App 进程里同时提供了托管运行时(ART)、Native 能力(JNI/NDK + 系统 C/C++ 库)、以及可嵌入的渲染/执行容器(WebView、FlutterEngine、游戏引擎 Surface),上层都统一挂到同一套窗口、输入、生命周期和系统服务上。
  • XML View 体系和 Jetpack Compose 到底只是“写法不同”,还是运行时架构已经变了?
    • 一句话答:不是只有语法不同;View 是命令式操作 View 树,更新靠 invalidate/requestLayout 驱动遍历,Compose 是声明式运行时,靠 snapshot 读写追踪、slot table 和记忆化重组来决定哪些节点重新执行。
  • Flutter 工程师看 Android 架构时,最该把哪几个宿主边界看清?
    • 一句话答:最该看清的是“Flutter 不是脱离 Android 运行”,它仍要依附 Android 进程、线程、窗口、输入、Binder 和生命周期;只是 UI 渲染与业务代码多了一层 Flutter engine/runtime。

对目标读者来说,这页真正要解决的不是入门定义,而是三件事:

  1. 把 Android 现有经验重新收束成一张稳定的体系地图。
  2. 把 Looper / Binder / 生命周期 / 启动 / ViewModel / Compose / Flutter 宿主这些专题放回统一坐标系。
  3. 建立“Android 为什么能容纳多技术栈形态”的解释能力,而不是只会背 API。

底层机制 ​

1. 先把 Android 放回一张分层图 ​

这张图不是教材式“从上到下背名词”,而是帮助你判断:代码写在哪层、问题发生在哪层、优化应落在哪层。

可以把它按“谁给谁提供能力”来理解:

层级你平时直接接触什么它向上一层提供什么常见问题落点
应用层Activity、Fragment、Compose、ViewModel、WebView、Flutter 宿主业务页面、状态、交互、插件接入生命周期错位、主线程阻塞、状态丢失
FrameworkContext、AMS/WMS/PMS、View System、Looper/Handler、资源系统组件模型、窗口、输入、权限、调度启动/返回栈/ANR/配置变更
RuntimeART、ClassLoader、GC、JNIJava/Kotlin 执行环境、托管堆、语言桥接冷启动、GC 抖动、JNI 边界
NativeBinder、SurfaceFlinger、Skia、MediaCodec、SQLite、WebView 内核IPC、渲染、媒体、数据库、浏览器内核Binder 卡顿、渲染瓶颈、图片/视频链路
KernelBinder driver、调度器、内存与设备驱动线程调度、进程隔离、驱动访问系统级阻塞、I/O、驱动、OOM/LMK

这张图里有三个容易混淆的点:

  • Framework 不是 Runtime
    • 一句话答:Framework 是 Android 对应用暴露的系统 API 与组件契约;Runtime 是 Java/Kotlin 代码真正被执行、回收、装载的环境。
  • Native 不只等于“你写 NDK”
    • 一句话答:更大量的 Native 能力其实来自 Android 自己的系统库和系统服务,例如 Binder、Skia、SurfaceFlinger、WebView 内核、媒体栈。
  • App 层技术形态可以不同,但最终都要落回同一宿主平台
    • 一句话答:无论你写的是 XML View、Compose、Flutter 还是 WebView 页面,最后都要依附同一个 Android 进程、窗口系统、输入通道、生命周期和系统服务。

2. 线程、消息循环、组件模型在整体中的位置 ​

先读细节专题: Android 主线程消息循环:Looper / Handler / MessageQueue · Android ANR 触发机制、排障定位与防范

Android 的“应用执行现场”可以拆成三条线:

  1. 线程线:代码最终在哪条线程上执行。
  2. 消息循环线:主线程如何串行处理输入、生命周期、布局、绘制、回调。
  3. 组件模型线:Framework 何时创建/恢复/暂停/销毁你的 Activity、Service、Receiver、Provider。

把它们放回分层图后,关系会更清楚:

text
Kernel 调度线程
→ Runtime/Framework 在主线程初始化 Looper
→ Framework 通过 MessageQueue 分发生命周期 / 输入 / 绘制 / IPC 回调
→ App 代码在 Activity / Fragment / View / Compose / Service 中执行

更具体一点:

  • 线程:底层由 Linux Kernel 调度,ART/Framework 只是借这些线程跑 Java/Kotlin 代码。
  • Looper / MessageQueue / Handler:属于 Framework 侧对主线程执行模型的封装,是 Android 把“单线程 UI + 消息驱动”落地的关键。
  • 组件生命周期:由 AMS、ActivityThread、Instrumentation、FragmentManager 等 Framework 机制调度,本质上还是通过主线程消息回调进入你的代码。

所以,下面这些看似不同的问题,其实都在同一个交点上:

问题本质上卡在哪典型专题
点击没反应 / ANR主线程消息队列被堵Android ANR 触发机制、排障定位与防范
runOnUiThread / Dispatchers.Main 为什么有效往主线程 Looper 投递恢复任务Android 主线程消息循环:Looper / Handler / MessageQueue
页面返回后又重复请求生命周期回调边界用错Android 生命周期总览
ViewModel 旋转后还活着组件重建与状态容器边界不同ViewModel 架构、SavedStateHandle 与进程被杀恢复
首帧慢 / 掉帧主线程与渲染管线的同步点失控Android App 进程启动全流程 (Zygote → ActivityThread → 首帧)

一句话收束:

  • 线程回答“谁在跑”。
  • Looper/MessageQueue回答“主线程按什么顺序跑”。
  • 组件模型回答“系统什么时候让你跑哪段代码”。

3. 为什么 Android 能承载 Java/Kotlin + Native + WebView/Flutter 等多种形态 ​

Android 的开放性不是“什么都能塞进去”,而是它在同一个 App 进程内同时提供了三种基础承载能力:

能力层你得到的能力典型技术形态为什么能共存
托管运行时GC、ClassLoader、反射、Kotlin/Java APIJava / Kotlin / Jetpack都运行在 ART 上,吃同一套 Framework API
Native 桥接JNI、NDK、C/C++ 库、Surface、EGL、媒体编解码游戏引擎、音视频、图像、加密、数据库通过 JNI/NativeActivity/Surface 与系统能力打通
可嵌入容器浏览器内核或跨端引擎WebView、FlutterEngine、React Native、小游戏容器都把渲染结果挂到 Android Window/View/Surface 上,并受生命周期与输入系统约束

你可以把 Android 想成“宿主操作系统 + 应用运行平台”,它允许多技术栈共存,但要求它们服从几个公共边界:

  1. 进程与权限边界:都运行在 Android 应用沙箱里。
  2. 生命周期边界:都要跟随 Activity/Fragment/Application/Process 的可见性与存活性。
  3. 线程边界:都受主线程响应、渲染线程、后台线程分工影响。
  4. 系统服务边界:都通过 Binder/Framework API 请求相机、定位、通知、窗口、包管理等能力。

3.1 Java / Kotlin:最“原生”的托管层应用形态 ​

这条线最贴近 Android 官方应用模型:

  • UI:XML View 或 Compose
  • 业务逻辑:Java/Kotlin
  • 状态:ViewModel / Flow / SavedStateHandle
  • 系统能力:Framework API + Binder 服务

它的优势是组件模型和平台能力耦合最自然,代价是需要直接面对生命周期、主线程、权限与设备碎片化。

3.2 Native / JNI / NDK:为了性能、复用和系统级能力 ​

Native 被引入通常不是为了“写得更底层更酷”,而是为了几类现实诉求:

  • 复用已有 C/C++ 能力:音视频、图像算法、协议栈、数据库、游戏引擎。
  • 追求更高性能或更低延迟:编解码、渲染、推理、加密。
  • 需要直接触碰系统底层能力:EGL、OpenGL/Vulkan、AImageReader、AAudio 等。

但 Native 并不会绕开 Android 宿主:

  • 页面显示仍要进 Window/Surface。
  • 权限申请仍走 Framework。
  • 生命周期仍由 Activity/Process 管。
  • 线程阻塞照样能拖垮主线程或 Binder 线程。

3.3 WebView:把浏览器内核嵌入 Android 组件模型 ​

WebView 之所以强,不是因为它“像网页”,而是因为它把一个浏览器运行时嵌进了 Android 页面:

  • Android 负责宿主窗口、生命周期、权限、进程与系统服务。
  • WebView 负责 HTML/CSS/JS 执行与页面渲染。
  • 原生与 H5 通过 JSBridge / URL Scheme / MessageChannel 之类机制通信。

这意味着 WebView 不是“脱离 Android 的第二世界”,而是“浏览器容器挂在 Android 宿主里”。因此 WebView 的登录态、权限、文件选择、回退栈、性能与崩溃排查,都要同时看 H5 和宿主两边。

3.4 Flutter:自带 UI Runtime,但仍是 Android 宿主上的来宾 ​

Flutter 经常被误解成“和 Android 平级”。更准确的说法是:

  • Flutter 自带 Dart runtime 和 engine。
  • 但 FlutterEngine 运行在 Android App 进程里。
  • FlutterActivity / FlutterFragment / FlutterView 仍依附 Android 的 Activity、Window、输入、生命周期。
  • 插件调用仍需要通过 Platform Channel 回到 Android 宿主,最终调用 Binder/Framework/系统服务。

所以 Flutter 在 Android 上的边界判断应该是:

  • Dart UI 逻辑 不等于 Android 宿主生命周期。
  • Flutter 的 UI isolate / raster / platform 线程 只是多加了一层执行模型,不会取消 Android 主线程、Binder、输入分发、权限和窗口系统的存在。
  • Flutter 页面卡顿 仍可能源自 Android 宿主侧的主线程阻塞、平台通道阻塞或系统渲染瓶颈。

对 Flutter 工程师最重要的一句话是:Flutter 替换的是 UI runtime,不是 Android 作为宿主平台的底座。

3.5 Android / Compose / Flutter 宿主关系图 ​

如果你已经熟悉 Android 和 Flutter,这里最值得一眼看清的不是 API 名词,而是宿主层级到底怎么套:Activity/Fragment 决定页面与生命周期边界,Compose 和 Flutter 分别是挂在 Android 宿主里的两种内容 runtime,但它们挂载的位置、对窗口/渲染的接管范围并不一样。

这张图里最关键的是三层边界:

  • Android App / Activity / Fragment 是宿主层级
    • 一句话答:它们决定进程内页面挂载点、窗口归属、返回栈、配置变更与生命周期分发,Compose 和 Flutter 都不能绕开这一层。
  • Compose 运行在 Android ViewSystem 之内
    • 一句话答:Compose 通过 ComposeView 或 setContent 挂进现有 View/Window 体系,生命周期和窗口仍由 Activity/Fragment/ViewTree 管,Compose 主要接管的是内容描述与最小更新。
  • Flutter 运行在 Android 宿主之上但自带 engine/runtime
    • 一句话答:Flutter 会把 FlutterView 挂到 Android 页面里,再由 FlutterEngine + Dart isolate 负责自身 UI 树和渲染线程;它接管的是内容 runtime,不是 Android 的窗口与宿主生命周期。

对混合栈判断最有用的收束可以记成一句话:Android 宿主边界通常止于 Activity / Fragment / Window / View 挂载点;Compose 边界大致止于 Compose 内容树;Flutter 边界大致止于 FlutterView 之内的 engine + Dart UI 内容。

4. XML View 体系 vs Jetpack Compose:不是换语法,而是换运行时架构 ​

相关主题: Android View 绘制流程、Choreographer 与 VSync 帧同步 · Jetpack Compose 状态模型、StateFlow 与重组优化

很多团队会把 Compose 说成“少写 XML、写法更现代”,这个说法太浅。真正重要的是:Compose 把 UI 更新模型从“操作现有 View 对象”改成了“根据状态重新计算 UI 描述,并让 runtime 决定最小更新范围”。

4.1 总结对比表 ​

维度XML View 体系Jetpack Compose你该如何理解
编程范式命令式 / 对象式声明式 / 状态驱动一个是在改树上的对象,一个是在重算 UI 描述
UI 载体View 树 / ViewGroup 层级Composition + Slot Table + LayoutNodeView 是真实对象树;Compose 运行时维护组合结构与记忆表
更新入口findViewById、属性 setter、invalidate/requestLayout状态变化触发 recompositionView 靠显式改对象;Compose 靠状态驱动重新执行受影响函数
脏区传播依赖 invalidate、requestLayout、遍历树依赖 snapshot 读写追踪、stability、skip/recomposeView 更偏“树遍历”,Compose 更偏“订阅哪些状态、重跑哪些节点”
状态边界容易散落在 View、Adapter、Fragment 字段倾向提升到 remember / rememberSaveable / ViewModelCompose 强迫你更明确区分瞬时状态与页面状态
渲染边界ViewRootImpl 的 measure/layout/drawComposition → Layout → Draw两者最终都受 VSync 驱动,但中间 runtime 不同
可测试性UI 与对象副作用常耦合Stateless Composable 更容易拆分和预览Compose 更鼓励状态提升和纯渲染函数

4.2 一张示意图看出差异 ​

这张图有三个核心判断:

  • View 体系的第一反应是“改对象”
    • 一句话答:页面已经有一棵真实 View 树,更新通常是拿到某个 View/Adapter 后直接改属性,再请求系统重绘或重排。
  • Compose 的第一反应是“改状态”
    • 一句话答:你通常不去“命令一个 Text 变红”,而是改状态,让读取该状态的 Composable 在下一帧自动重组。
  • 两者最终都要进入布局和绘制,但更新前的中间层完全不同
    • 一句话答:View 依赖对象树与遍历;Compose 依赖 runtime 对状态读取关系、slot table 和记忆节点的维护。

4.3 进一步拆:View 树 vs Compose runtime / slot table / recomposition ​

View 树心智 ​

View 体系的经典思路是:

  1. inflate XML 得到对象树。
  2. 每个 View 持有自己的状态与属性。
  3. 业务代码通过引用直接修改这些对象。
  4. 通过 invalidate() / requestLayout() 让 ViewRootImpl 在下一帧重新遍历。

这种模式的优势是对象直观、调试简单、与平台 API 强绑定;缺点是状态容易散、局部刷新边界不稳定、复杂页面常出现 Adapter / View / Fragment / DataBinding 的耦合泥球。

Compose runtime 心智 ​

Compose 则换了问题定义:

  1. Composable 函数描述“当前状态下 UI 应该长什么样”。
  2. runtime 在组合时记录“谁读取了哪些状态”。
  3. 状态变更后,Recomposer 只让受影响节点重新执行。
  4. Slot table 负责记忆 remember 等组合位置相关数据。

这里最容易被忽略的是 slot table 的角色:它不是“另一棵 View 树”,而是 Compose runtime 维护的组合记忆表,用来记住当前组合结构、remember 的值、节点位置以及可跳过/需重组的信息。

渲染边界差异 ​
  • 在 View 里,边界通常是某个 View 或某片脏区域是否需要重新 measure/layout/draw。
  • 在 Compose 里,边界首先是某个 Composable 是否因为读取到的状态变化而需要重新执行;之后才进入 layout/draw。

所以 Compose 优化常见关注点会变成:

  • 这个状态是不是读得过宽,导致整个大 Composable 都重组?
  • 这个对象是否稳定(stable/immutable),能否跳过无意义重组?
  • 这份状态该不该放 remember、rememberSaveable、ViewModel,还是只做临时 UI state?

5. Android 架构里最值得优先建立的几组“交叉索引” ​

这一页本身不替代专题,而是给你建立索引关系。建议把下面几组组合一起复习:

5.1 执行与阻塞线 ​

这组回答:

  • 主线程怎么跑
  • 跨进程怎么调
  • 为什么会 ANR
  • 为什么很多“偶发卡死”其实是 Binder、锁、主线程消息队列交叉阻塞

5.2 生命周期与状态线 ​

这组回答:

  • 宿主什么时候重建
  • 页面状态应活到哪一层
  • ViewModel、SavedStateHandle、Compose state 的边界怎么分
  • Flutter 工程师最容易把“页面 state”和“宿主恢复 state”混在哪

5.3 启动与渲染线 ​

这组回答:

  • 进程怎么启动
  • 首帧为什么慢
  • VSync / Choreographer / measure-layout-draw 在哪接起来
  • 启动优化为什么必须同时看 Application、Provider、主线程、首帧与渲染

5.4 与 Flutter 的宿主对照线 ​

这组回答:

  • Flutter engine 线程和 Android 主线程怎么对照
  • 状态驱动 UI 在 Compose/Flutter 里哪里相似、哪里不一样
  • Platform Channel 为何最终还是回到 Android 宿主能力边界

Android / Flutter / Web / Backend 对照 ​

这里只保留对主线理解有帮助的对照,不做平均铺开。

维度AndroidFlutter(运行在 Android 上时)WebView/H5Backend
宿主平台Android OS + Framework + ART仍是 Android 宿主,只是 UI runtime 换成 Flutter engine + DartAndroid 宿主 + 浏览器内核通常无 UI 宿主,主要是进程/容器/网络协议
主执行模型主线程 + Looper + Binder + 生命周期回调UI isolate + engine threads,但仍受 Android Activity/Window/插件边界约束浏览器 JS event loop + Android 宿主生命周期线程池 / 协程 / 事件循环,少了 UI 帧驱动
UI 架构XML View / ComposeWidget / Element / RenderObjectDOM / CSSOM / JS无
系统能力接入直接 Framework / Binder APIPlatform Channel → Android 原生JSBridge / Web APIs + 宿主注入系统调用 / 中间件 / RPC
常见误判只会看页面 API,不会回到底层分层以为 Flutter 屏蔽了宿主问题以为 H5 问题完全与宿主无关把服务端模型直接类比 UI 生命周期

常见场景 ​

1. 你在做一个混合栈 App,为什么要先知道“当前问题落在哪层” ​

真实工程里最浪费时间的不是不会修,而是修错层:

  • 页面白屏,实际是启动链上某个 Provider 或主线程初始化拖慢。
  • Flutter 页面卡顿,实际是平台通道或原生主线程阻塞。
  • WebView 登录态错乱,实际是宿主 token 同步与 JSBridge 契约有洞。
  • Compose 页面频繁重组,实际是状态边界放错,不是“Compose 天生性能差”。

读完这页后,最起码要能先问自己:

  • 这是应用层问题、Framework 问题、Runtime 问题,还是 Native/Kernel 边界问题?
  • 是线程堵了、Binder 堵了、生命周期边界错了,还是渲染 runtime 自己的状态建模出了问题?

2. 你要解释“为什么 Android 能容纳这么多技术形态” ​

一个对外表达很常见的场景是架构评审或面试。更准确的回答不是:

  • Android 能跑 Java/Kotlin,因为有 JVM。
  • Android 能跑 Flutter,因为有插件。

而应是:

  • Android 作为宿主平台,提供了 组件模型、窗口系统、系统服务、权限、进程隔离、输入与渲染接入点。
  • Java/Kotlin 是默认托管层。
  • Native 是性能/系统能力层。
  • WebView/Flutter 是嵌入式执行与渲染容器。
  • 它们并列存在,但最终共用同一宿主边界。

3. 你在做 XML View → Compose 迁移时,该怎么判断“改的是语法还是架构” ​

如果迁移时你只是:

  • 把 XML 改成 Composable
  • 但状态仍散落在 Fragment 字段、Adapter、单例、回调里
  • 仍然习惯事件直接推 View,而不是让状态驱动 UI

那你改的只是语法皮,没有真正迁移架构。

更接近 Compose 正确迁移的信号是:

  • 页面状态被显式建模
  • Stateless UI 比例提高
  • 事件与状态分离
  • 页面级状态与宿主恢复状态分层明确
  • 重组边界和性能分析开始围绕“谁读了哪些状态”展开

常见误配、事故后果与排障 ​

误区典型后果排障切入点修法
把 Android 只当“Java UI 框架”解释不了 Binder、ANR、启动、WebView/Flutter 宿主问题先定位问题落在哪层用“App / Framework / Runtime / Native / Kernel”重建分析框架
把 Looper、生命周期、渲染看成互不相干页面卡顿、重复请求、状态丢失时只会局部修补看主线程消息、生命周期回调与首帧时序是否串起来以主线程执行现场为主线串起来分析
认为 Flutter/Compose 屏蔽了宿主边界平台调用卡顿、生命周期错位、恢复失败看宿主 Activity、Platform Channel、线程模型明确“新 UI runtime 不会抹掉 Android 宿主”
把 Compose 只理解成“少写 XML”迁移后代码更乱、重组失控看状态分层、重组范围、remember/ViewModel 边界按声明式 runtime 重建状态模型
不区分 Runtime 与 FrameworkGC、启动、ClassLoader、JNI 问题定位模糊看问题是 API 契约层,还是执行环境层用“Framework 提供规则,Runtime 提供执行环境”来拆

与相近概念对比 ​

概念更准确的边界
Android Framework系统对应用暴露的 API、组件模型、窗口与服务契约
Android Runtime (ART)Java/Kotlin 字节码执行、GC、ClassLoader、JNI 承载环境
Native 层Binder、图形、媒体、数据库、WebView 内核、系统 C/C++ 能力
XML View命令式对象树 UI 系统
Jetpack Compose声明式状态驱动 UI runtime
Flutter on Android自带 Dart + engine 的 UI runtime,运行在 Android 宿主中
WebView嵌入 Android 页面中的浏览器执行容器

对应实验 ​

本页当前作为总览索引页,不新增伪实验。请直接跳到已有专题对应的真实 lab:

文档说明对应实验
Android 主线程消息循环:Looper / Handler / MessageQueue主线程消息循环 / HandlerThreadlooper-handler-demo
Android Binder IPC 机制与跨进程通信Binder / Messenger / 跨进程通信binder-messenger-demo
Android ANR 触发机制、排障定位与防范主线程阻塞 / ANR 诊断anr-mechanism-demo
Android 生命周期总览生命周期 / 配置变更 / 进程恢复android-activity-lifecycle-basic 等
ViewModel 架构、SavedStateHandle 与进程被杀恢复ViewModel / SavedStateHandleviewmodel-savedstate-demo
应用启动性能优化实战(拓扑排序、异步初始化与首帧治理)启动打点与优化startup-timing-demo

复习检查题 ​

  1. 为什么说 Android 不是“一个 Java UI SDK”,而是一个分层平台?

    答:因为 App 层只是最上面一层;下面还有 Framework 提供组件模型与系统 API,ART 提供 Java/Kotlin 执行环境,Native 提供 Binder/图形/媒体/WebView 等核心能力,Kernel 再提供线程调度、内存和驱动。实际工程问题常常跨越多层,不能只盯着应用代码。

  2. 线程、Looper、生命周期三者各自回答什么问题?

    答:线程回答“谁在执行”;Looper/MessageQueue 回答“主线程按什么顺序串行执行消息”;生命周期回答“Framework 什么时候让你的组件进入哪些状态并执行哪些回调”。三者在主线程上汇合成 Android 页面的真实运行现场。

  3. 为什么 Android 能同时承载 Java/Kotlin、Native、WebView 和 Flutter?

    答:因为 Android 既提供托管运行时(ART),也提供 Native 能力(JNI/NDK + 系统库),还提供可嵌入容器(WebView、FlutterEngine)接入窗口、输入、生命周期与系统服务。不同技术形态可以共存,但最终仍依附同一个宿主平台边界。

  4. XML View 和 Compose 的最核心架构差异是什么?

    答:View 体系是命令式对象树,更新靠修改 View 对象属性并触发 invalidate/requestLayout;Compose 是声明式 runtime,更新靠状态变化触发 snapshot 追踪下的 recomposition,由 runtime 决定哪些组合节点重新执行。它们不是只差“写法”,而是更新模型与运行时结构都不同。

  5. 为什么 Flutter 工程师仍然需要理解 Android 宿主架构?

    答:因为 Flutter 在 Android 上只是替换了 UI runtime,并没有替换宿主平台本身。FlutterActivity、Platform Channel、权限、窗口、生命周期、Binder、启动与 ANR 仍然属于 Android 宿主边界;不理解这些边界,就解释不了大量真实线上问题。

速记 ​

  • Android = App 层 + Framework + ART + Native + Kernel,不是单一 UI SDK
  • 线程回答“谁跑”,Looper 回答“怎么排队跑”,生命周期回答“系统何时让你跑”
  • Java/Kotlin、NDK、WebView、Flutter 能共存,因为它们都挂在同一宿主平台上
  • View 是命令式对象树;Compose 是声明式状态驱动 runtime
  • Flutter 替换的是 UI runtime,不是 Android 宿主底座

站点构建时间:2026/8/24 23:43:17