Android View 绘制流程深度剖析

整体流程一览 ViewRootImpl.performTraversals() │ ├─── performMeasure() → View.measure() → onMeasure() │ ├─── performLayout() → View.layout() → onLayout() │ └─── performDraw() → View.draw() → onDraw() 一、Measure(测量) 核心机制 父 View 把测量约束封装进 MeasureSpec(一个 32 位 int,高 2 位是模式,低 30 位是尺寸)传给子 View,子 View 在 onMeasure() 中根据约束计算自己的期望尺寸,最后调用 setMeasuredDimension() 提交结果。 三种模式: 模式 含义 典型来源 EXACTLY 精确值,例如 100dp 或 match_parent 父有确定尺寸 AT_MOST 不超过某个上限,例如 wrap_content 父允许子自由伸缩 UNSPECIFIED 没有限制,ScrollView 内的子 View 父不关心大小 wrap_content 失效 这是自定义 View 最高频的 bug。如果自定义 View 继承自 View(而非 TextView 等),不重写 onMeasure,它默认调用父类实现,而父类对 AT_MOST 和 EXACTLY 的处理是一样的——直接使用父传来的 size,效果等同于 match_parent。 ...

April 1, 2026 · 5 min

Jetpack LiveData 原理笔记

梳理 Jetpack LiveData 的核心设计。

March 27, 2026 · 1 min

ViewModel 实现原理:为什么屏幕旋转后数据不丢失

一篇简明笔记,解释 ViewModel 为什么能跨屏幕旋转存活,以及带参数的 ViewModel 应该如何创建。

March 27, 2026 · 1 min

Android 四大组件与生命周期要点

Activity 生命周期是什么? onCreate:初始化视图、数据恢复 onStart:页面可见 onResume:页面处于前台,可交互 onPause:失去焦点,轻量释放 onStop:完全不可见,重资源释放 onDestroy:销毁前清理,但不保证一定执行 加上一个onrestart 启动模型 跳转时: 旧 Activity 先 onPause,新 Activity 启动后,旧的再 onStop。 切回主界面时: onRestart -> onStart -> onResume。 activity的启动模式 (LaunchMode) 及场景 Standard: 默认模式,每次启动都创建新实例。 SingleTop: 栈顶复用。场景: 通知栏点击进入已打开的页面,避免重复创建。 SingleTask: 栈内复用,会移除其上方的所有 Activity。场景: APP 主页。 SingleInstance: 独占一个任务栈。场景: 闹钟、来电显示。 屏幕旋转后的 Activity 重建 原理: 默认会执行销毁并重建流程。 处理方案: 持久化: 在 onSaveInstanceState 中保存 Bundle 数据,在 onCreate 或 onRestoreInstanceState 中恢复。 ViewModel: 利用 ViewModel 生命周期长于 Activity 的特性存储 UI 数据。可以详细了解Viewmodel 中的过程。 配置拦截: 在 Manifest 设置 android:configChanges=“orientation|screenSize”,拦截后在 onConfigurationChanged 中手动处理。 ...

March 25, 2026 · 5 min

MVC、MVP、MVVM 架构模式

MVC、MVP、MVVM 架构模式 这三种模式都是为了解决同一个核心问题:将 UI(视图)与业务逻辑(模型)解耦,让代码更易维护、可测试。 MVC(Model - View - Controller) 角色分工 角色 在 Android 中 职责 Model 数据层(网络、数据库、Repository) 数据的获取与处理 View XML 布局文件 负责界面展示 Controller Activity / Fragment 接收用户输入,协调 Model 和 View 核心问题 Android 中 MVC 的致命缺陷是:Activity/Fragment 既是 Controller 又是 View。 Activity 本身要 setContentView(View 的职责),又要处理点击事件与数据请求(Controller 的职责),导致 Activity 越来越臃肿。 // 典型的 MVC Activity,臃肿的 "上帝类" class UserActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_user) // View 的职责 btnLoad.setOnClickListener { // Controller 的职责:响应事件 // 直接调用网络,夹杂在 Activity 中 UserApi.getUser(userId) { user -> // Model 的职责 tvName.text = user.name // 又直接操作 View } } } } 问题总结: ...

March 18, 2026 · 5 min

Android 悬浮窗前后台自动显隐方案设计

一、需求背景与核心挑战 功能需求 需实现一个全局悬浮窗(Floating View),具体行为规范如下: 应用位于前台时,隐藏悬浮窗,避免遮挡用户正常操作。 应用退至后台时,显示悬浮窗,使其保持悬浮于系统或其他应用界面之上。 核心挑战 悬浮窗通常由独立的 Service 组件维护,以确保其生命周期独立于 Activity。因此,该需求的技术难点在于:在后台运行的 Service 如何实时、准确地感知当前应用的前后台状态切换? 二、悬浮窗实现的核心原理剖析 在阐述具体代码方案前,需明确通过"前台 Service + WindowManager"实现悬浮窗效果的底层原理。此机制主要涉及 Android 的显示架构与进程保活策略: 2.1 Android 的窗口层级体系 (Z-order) Android 的显示系统并非局限于各个应用单独绘制自身区域。屏幕上的所有渲染内容均由 WindowManagerService (WMS) 统一管理。WMS 维护着一个全局的窗口 Z-order 栈,不同类型的窗口对应不同的显示层级: 系统窗口层(System Window):最高层级,包含状态栏、导航栏、Toast、悬浮窗等。 子窗口层(Sub Window):中间层级,包含 Dialog、PopupWindow 等(需依附于宿主窗口)。 应用窗口层(Application Window):最底层级,对应普通 Activity 的窗口。 由于系统窗口层的 Z-order 高于应用窗口层,将窗口类型配置为系统级,即可实现覆盖于所有应用之上的"悬浮"效果。 2.2 WindowManager.addView() 的底层机制 调用 WindowManager.addView(view, params) 时,系统底层的实际调用链路如下: 应用层代码 → WindowManager (客户端代理) → Binder IPC → WindowManagerService (系统服务端) → SurfaceFlinger (合成渲染) 传入的 LayoutParams.type 参数决定了目标 View 所属的显示层级。当参数配置为: params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY WMS 会将该窗口分配至系统窗口层。该窗口独立于任何 Activity 的生命周期,直接由系统 WMS 管理,其 Z-order 默认高于所有普通 Activity,从而呈现悬浮状态。 ...

March 15, 2026 · 3 min