
Android Jetpack Compose 深度探索:状态、动画与性能
Jetpack Compose 已成为 Android UI 开发的标准。随着 Compose BOM 2026.x 的发布,稳定性极佳,API 表面丰富。本指南深入探讨状态管理、动画、性能优化以及 View 系统集成的高级模式。
理解组合与状态

状态提升模式
// 无状态组件 - 易于测试和复用
@Composable
fun EmailInput(
value: String,
onValueChange: (String) -> Unit,
isError: Boolean = false,
modifier: Modifier = Modifier,
) {
OutlinedTextField(
value = value,
onValueChange = onValueChange,
label = { Text("Email") },
isError = isError,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
modifier = modifier,
)
}
使用 StateFlow 的 ViewModel
@HiltViewModel
class LoginViewModel @Inject constructor(
private val authRepository: AuthRepository,
) : ViewModel() {
private val _uiState = MutableStateFlow(LoginUiState())
val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
fun login() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
authRepository.login(_uiState.value.email, _uiState.value.password)
.onSuccess { _uiState.update { it.copy(isLoading = false, loginSuccess = true) } }
.onFailure { e -> _uiState.update { it.copy(isLoading = false, errorMessage = e.message) } }
}
}
}
data class LoginUiState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val loginSuccess: Boolean = false,
val errorMessage: String? = null,
)
高级 Compose 动画
带自定义过渡的 AnimatedVisibility
@Composable
fun NotificationBanner(message: String?, onDismiss: () -> Unit) {
AnimatedVisibility(
visible = message != null,
enter = slideInVertically(
initialOffsetY = { -it },
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow,
)
) + fadeIn(),
exit = slideOutVertically(targetOffsetY = { -it }) + fadeOut(),
) {
Surface(
color = MaterialTheme.colorScheme.inverseSurface,
shape = RoundedCornerShape(12.dp),
modifier = Modifier.fillMaxWidth().padding(16.dp),
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(message ?: "", modifier = Modifier.weight(1f))
IconButton(onClick = onDismiss) {
Icon(Icons.Default.Close, "Dismiss")
}
}
}
}
}
动画化状态
@Composable
fun ProgressButton(progress: Float, onClick: () -> Unit, modifier: Modifier = Modifier) {
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = tween(durationMillis = 600, easing = FastOutSlowInEasing),
label = "progress",
)
val backgroundColor by animateColorAsState(
targetValue = if (progress >= 1f)
MaterialTheme.colorScheme.tertiary
else
MaterialTheme.colorScheme.primary,
label = "background",
)
Box(
modifier = modifier
.clip(RoundedCornerShape(50))
.background(backgroundColor)
.clickable(onClick = onClick)
.padding(horizontal = 24.dp, vertical = 12.dp),
) {
LinearProgressIndicator(
progress = { animatedProgress },
modifier = Modifier.fillMaxWidth().height(4.dp).align(Alignment.BottomCenter),
)
Text(
text = if (progress >= 1f) "Done!" else "${(progress * 100).toInt()}%",
color = Color.White,
fontWeight = FontWeight.SemiBold,
)
}
}

性能优化
避免不必要的重组
// 使用 rememberUpdatedState 处理回调
@Composable
fun OptimalExample(count: Int, onCountChanged: (Int) -> Unit) {
val currentOnCountChanged by rememberUpdatedState(onCountChanged)
Button(onClick = { currentOnCountChanged(count + 1) }) {
Text("Count: $count")
}
}
使用 derivedStateOf 进行昂贵计算
@Composable
fun SortedList(items: List<Item>) {
val listState = rememberLazyListState()
val sortedItems by remember(items) {
derivedStateOf { items.sortedBy { it.priority } }
}
val showScrollToTop by remember {
derivedStateOf { listState.firstVisibleItemIndex > 3 }
}
Box {
LazyColumn(state = listState) {
items(sortedItems, key = { it.id }) { item ->
ItemRow(item = item)
}
}
AnimatedVisibility(
visible = showScrollToTop,
modifier = Modifier.align(Alignment.BottomEnd),
) {
FloatingActionButton(
onClick = { /* 滚动到顶部 */ },
modifier = Modifier.padding(16.dp),
) {
Icon(Icons.Default.KeyboardArrowUp, "Scroll to top")
}
}
}
}
Stable 和 Immutable 注解
@Immutable
data class UserProfile(
val id: String,
val name: String,
val avatarUrl: String,
val bio: String,
)
@Stable
class CartState {
var items by mutableStateListOf<CartItem>()
val total: Double get() = items.sumOf { it.price * it.quantity }
}
Compose 与 View 互操作

在 Fragment 中嵌入 Compose
class MyFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
MaterialTheme {
val viewModel: MyViewModel by viewModels()
MyComposableScreen(viewModel = viewModel)
}
}
}
}
}
在 Compose 中嵌入 Android View
@Composable
fun LegacyMapView(latLng: LatLng, modifier: Modifier = Modifier) {
val mapView = rememberMapViewWithLifecycle()
AndroidView(
factory = { mapView },
modifier = modifier,
update = { view ->
view.getMapAsync { map ->
map.moveCamera(CameraUpdateFactory.newLatLng(latLng))
}
},
)
}
Lazy 布局优化
@Composable
fun OptimizedFeed(items: List<FeedItem>, onItemClick: (FeedItem) -> Unit) {
LazyColumn(
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
items(
items = items,
key = { item -> item.id },
contentType = { item -> item::class.simpleName },
) { item ->
FeedItemCard(
item = item,
onClick = { onItemClick(item) },
modifier = Modifier.animateItem(),
)
}
}
}
Compose Multiplatform
Compose Multiplatform 支持在 Android、iOS、桌面和 Web 之间共享 UI 代码:
// 共享 UI 代码
@Composable
fun SharedProfileCard(user: User, modifier: Modifier = Modifier) {
Card(modifier = modifier.fillMaxWidth()) {
Row(modifier = Modifier.padding(16.dp)) {
AsyncImage(
model = user.avatarUrl,
contentDescription = null,
modifier = Modifier.size(48.dp).clip(CircleShape),
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(user.name, style = MaterialTheme.typography.titleMedium)
Text(user.bio, style = MaterialTheme.typography.bodySmall)
}
}
}
}
结论
Jetpack Compose 随着每个版本的发布而不断成熟。掌握状态提升、ViewModel 集成、动画 API 和性能优化,能够帮助你构建美观且响应迅速的 Android 应用。与旧版 View 的互操作故事意味着你可以在现有项目中逐步采用 Compose,而新项目则受益于 Android 历史上最佳的开发者体验。