基础概念
-
什么是 Jetpack Compose?它与传统 Android UI 开发有何不同?
- Compose 是 Android 的现代声明式 UI 工具包,使用 Kotlin 编写
- 不同于传统的基于 View 和 XML 的 imperative 方式,Compose 使用声明式范式
- 主要区别:无 XML 布局、无 findViewById、状态驱动 UI、组合优于继承
-
解释 Compose 中的声明式 UI 模型
- 描述 UI 应该是什么样子,而不是如何逐步构建它
- UI 是应用状态的函数:UI = f(state)
- 当状态变化时,Compose 自动重新组合(recompose)受影响的组件
-
Composable 函数的特点是什么?
- 使用
@Composable
注解标记 - 可以调用其他 Composable 函数
- 无返回值(返回 Unit),因为它们描述 UI 而不是构造 UI 对象
- 可以接受参数并保持本地状态
- 应该是幂等的和没有副作用的
- 使用
状态管理
-
解释 Compose 中的状态和记忆(remember)
- 状态是随时间变化的值,当状态变化时会导致重组
remember
在重组期间保存值,避免每次重组都重新初始化mutableStateOf
创建可观察状态,当其值变化时通知 Compose
-
State Hoisting(状态提升)是什么?为什么重要?
- 将状态移动到调用者的更高层次,使组件无状态
- 重要原因:提高可重用性、使组件更容易测试、实现单一数据源
- 模式:用参数传递状态值,用 lambda 传递事件回调
-
比较
remember
和rememberSaveable
remember
只在配置更改期间保持状态(如旋转屏幕会丢失)rememberSaveable
使用 SavedStateHandle 在进程死亡和配置更改后恢复状态rememberSaveable
可以自动保存基本类型和 Parcelable 类型,或通过自定义 Saver
主题和样式
-
如何在 Compose 中实现主题和样式?
- 使用
MaterialTheme
提供颜色、排版和形状 - 可以自定义主题属性:
MaterialTheme(colors = ..., typography = ..., shapes = ...)
- 通过
MaterialTheme.colors.primary
等方式访问主题值
- 使用
-
解释 Compose 中的
Modifier
系统- Modifier 是用于装饰或增强组件的链式调用
- 可以添加 padding、大小、背景、点击行为等
- 顺序很重要:
Modifier.padding(10).size(50)
与Modifier.size(50).padding(10)
不同
布局和组合
-
Compose 中的基本布局组件有哪些?
Column
- 垂直排列子项Row
- 水平排列子项Box
- 堆叠子项ConstraintLayout
- 复杂布局,支持相对定位
-
如何创建自定义布局?
- 使用
Layout
可组合函数 - 实现
MeasurePolicy
定义测量和布局逻辑 - 示例:自定义流式布局、环形布局等
- 使用
性能优化
-
解释 Compose 的重组(Recomposition)机制
- 当输入变化时,Compose 会智能地只重组必要的组件
- 使用
@Stable
和@Immutable
注解帮助 Compose 做出优化决策 - 通过结构相等性比较 (
equals
) 决定是否需要重组
-
如何优化 Compose 性能?
- 使用
remember
避免不必要的计算 - 将大列表分成更小组件
- 对列表使用
LazyColumn
/LazyRow
- 避免在组合期间执行昂贵操作
- 使用
derivedStateOf
减少不必要的重组
- 使用
高级主题
-
如何在 Compose 中处理副作用?
- 使用副作用 API:
LaunchedEffect
,DisposableEffect
,SideEffect
LaunchedEffect
用于协程作用域内的副作用DisposableEffect
用于需要清理的资源rememberCoroutineScope
获取与组合生命周期绑定的协程作用域
- 使用副作用 API:
-
解释 Compose 中的
CompositionLocal
- 隐式传递依赖项的机制,避免显式参数传递
- 常见用例:主题、配置、本地化等
- 通过
CompositionLocalProvider
提供值,LocalXXX.current
获取值
-
如何将传统 View 集成到 Compose 中?
- 使用
AndroidView
可组合函数 - 通过
update
回调响应状态变化 - 对于自定义 View,实现
ViewBinding
或AndroidViewBinding
- 使用
实际应用
-
如何在 Compose 中实现导航?
- 使用
Navigation
组件与 Compose 集成 - 定义
NavHost
和可组合目的地 - 通过
rememberNavController()
获取NavController
- 使用
navigate()
和popBackStack()
管理导航栈
- 使用
-
Compose 中如何处理图片加载?
- 使用
Coil
或Glide
的 Compose 扩展 AsyncImage
(Coil) 或GlideImage
(Glide)- 支持占位符、错误图像、转换等
- 使用
-
如何在 Compose 中测试 UI?
- 使用
ComposeTestRule
进行 UI 测试 onNodeWithText
,onNodeWithTag
等查找节点performClick()
,performScrollTo()
等交互操作assertIsDisplayed()
,assertTextEquals()
等断言
- 使用
架构模式
-
如何在 MVVM 架构中使用 Compose?
- ViewModel 持有和管理状态
- Compose UI 观察 ViewModel 的状态
- 使用
viewModel()
函数获取 ViewModel 实例 - 事件通过 ViewModel 暴露的方法处理
-
Compose 如何与数据流(如 Flow、LiveData)集成?
- 使用
collectAsState()
将 Flow 转换为 Compose 状态 LiveData.observeAsState()
用于 LiveData- 在
LaunchedEffect
中收集流,当键变化时取消并重新启动
- 使用
常见问题解决
-
如何处理 Compose 中的键盘和输入法?
- 使用
SoftwareKeyboardController
控制键盘 imePadding()
修饰符避免键盘遮挡内容focusRequester
管理输入焦点
- 使用
-
Compose 中的动画如何实现?
- 使用
animate*AsState
函数创建简单动画 updateTransition
管理多个动画值AnimatedVisibility
显示/隐藏动画rememberInfiniteTransition
无限动画
- 使用
-
如何调试 Compose 应用?
- 使用
debugInspectorInfo
检查修饰符 - 重组计数调试:
debugLogRecomposition
- 布局检查器支持 Compose
- 使用
compositionLocalOf
传递调试工具
- 使用
最新特性
-
Compose 1.2+ 中的新特性有哪些?
- 延迟布局改进(LazyLayout API)
- 可下载字体支持
- 嵌套滚动互操作改进
- 新的动画 API 和效果
-
Compose Multiplatform 的现状如何?
- 支持 Android、Desktop 和 Web
- 共享 UI 代码跨平台
- 特定平台 API 通过 expect/actual 机制处理
希望这份全面的 Compose 面试题整理对您有所帮助!根据具体职位要求,可以重点准备相关领域的问题。