小米Compose专项面试:小米Android开发覆盖MIUI系统定制、IoT设备互联。技术栈偏底层,面试官喜欢问系统级原理和性能数据。技术方向偏向MIUI定制、IoT互联。特色专项包括MIUI系统定制与IoT设备开发。今天8道题覆盖小米Compose专项面试核心考点。
Q1:Compose性能优化:稳定性(stability)和跳过(skippable)?
Compose性能核心是减少不必要的重组。1)稳定类型(Stable)——所有字段不可变(val+稳定类型),Compose可以安全跳过重组。不稳定的类型(如List/Map)每次都触发重组;2)@Stable/@Immutable注解——手动标记类型为稳定;3)remember derivedStateOf——只有派生结果变化才重组;4)避免lambda分配——用remember包裹lambda或定义在Composable外部。compose compiler report可以分析哪些Composable是skippable的。
// 不稳定——List每次都重组
data class UiState(val items: List<Item>) // List不稳定
// 稳定——用ImmutableList
@Immutable
data class UiState(val items: ImmutableList<Item>)
// 或用@Stable标记
@Stable
data class UiState(val items: List<Item>)
追问:怎么检查Composable是否可跳过?composeCompilerReports生成报告,skipscolumn显示true/false。不可跳出的原因是参数类型不稳定。
Q2:Compose自定义Layout怎么实现?
用Layout composable代替Box/Column/Row实现自定义布局。核心:measurables(子元素列表)→测量每个子元素→确定总体大小→place放置子元素。本质跟View体系的onMeasure+onLayout一样,只是用了声明式API。
@Composable
fun StaggeredGrid(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
Layout(content = content, modifier = modifier) { measurables, constraints ->
val placeables = measurables.map { it.measure(constraints) }
layout(constraints.maxWidth, constraints.maxHeight) {
var y = 0
placeables.forEach { p -> p.placeRelative(x = 0, y = y); y += p.height }
}
}
}
追问:自定义Layout时intrinsic测量什么时候用?需要根据子元素的内在尺寸来计算自身尺寸时用——如Text的宽度按内容计算。
Q3:Compose动画的核心API?
animateXxxAsState——最简单的单值动画(animateColorAsState, animateDpAsState等);Animatable——更精细控制的动画(支持spring/tween等);Transition——多属性同步动画(如状态切换时多个属性一起动);AnimatedVisibility——显示/隐藏动画(expand/shrink/fade/slide)。底层都基于协程和差值器。
val isExpanded by remember { mutableStateOf(false) }
val rotation by animateFloatAsState(
targetValue = if (isExpanded) 180f else 0f,
animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy)
)
Icon(modifier = Modifier.rotate(rotation), ...)
追问:Compose动画和View动画的区别?Compose动画基于State驱动+协程,声明式且与重组自然集成;View动画基于属性+时间。
Q4:Compose主题和Material3适配?
MaterialTheme提供Color/Typography/Shapes三套设计令牌。ColorScheme定义主题色——Material3支持Dynamic Color(Monet, 从壁纸提取调色板)。Typography定义文字层级(display/headline/title/body/label)。Shapes定义组件形状(圆角等)。在@Composable中通过MaterialTheme.colors/typography/shapes自动获取当前主题值。
@Composable
fun MyAppTheme(darkTheme: Boolean, content: @Composable () -> Unit) {
val colorScheme = if (darkTheme) darkColorScheme(
primary = Purple80, secondary = PurpleGrey80
) else lightColorScheme(
primary = Purple40, secondary = PurpleGrey40
)
MaterialTheme(colorScheme = colorScheme, typography = Typography, content = content)
}
追问:Dynamic Color的兼容性?Android 12+原生支持,低版本需要用androidx.compose.material3:material3兼容库。
Q5:Compose测试和UI预览?
Compose测试用createComposeRule——在JVM上运行Composable并断言UI状态。核心API:onNodeWithText/onNodeWithTag查找节点,performClick/performTextInput模拟交互,assertExists/assertTextEquals断言。Preview是@Preview注解——编译时在IDE中渲染Composable预览,支持多设备/深色模式/字体大小预览。@PreviewLightDark/@PreviewFontScale自动生成多种配置预览。
@Composable
fun Greeting(name: String) { Text("Hello, $name!") }
@Preview(showBackground = true)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun GreetingPreview() { Greeting("Android") }
追问:怎么测试有ViewModel的Composable?用createComposeRule + hiltViewModel需要Hilt测试环境,或直接传入mock ViewModel。
Q6:Compose的副作用(effect)API?
Compose函数应该纯函数无副作用,副作用用Effect API管理:LaunchedEffect(key)——key变化时在协程中执行(如首次加载数据);DisposableEffect(key)——需要清理的副作用(如注册/注销监听器);SideEffect——每次重组后执行(将Compose状态同步到非Compose代码);rememberCoroutineScope——获取Composable绑定的协程作用域。
下一篇进入小米算法高频题——快速排序原理、两数之和(哈希表一次遍历)、有效的括号(栈的应用)。
觉得有用的同学扣1,你面试被追问最狠的是哪道题?
本系列连载中,关注不迷路,下一篇:小米算法高频题面经:快速排序原理、两数之和(哈希表一次遍历)、有效的括号(栈的应用)
系列简介:Android大厂面经连载,覆盖字节跳动、腾讯、阿里、美团等40+企业,从初级到架构师全岗位覆盖。每篇文章包含真实面试题+详细答案+代码示例,帮你拿到大厂Offer。