1. Jetpack Compose 布局基础解析
Jetpack Compose作为Android现代UI工具包,彻底改变了Android界面开发方式。与传统XML布局相比,Compose采用声明式编程范式,让开发者能够更直观地描述UI应该呈现的状态。在Compose的世界里,Scaffold、TopAppBar和BottomAppBar这三个组件构成了应用骨架的基础三角。
Scaffold作为"脚手架",提供了Material Design应用的标准布局结构。它就像建筑工地上的钢架,为其他组件提供了可靠的支撑和定位。在实际项目中,我发现Scaffold可以自动处理系统栏(状态栏和导航栏)的适配问题,这比传统方式节省了大量样板代码。
TopAppBar对应传统ActionBar/Toolbar,但功能更加强大。通过Compose实现的应用栏不再受限于固定模式,可以轻松创建折叠、透明、带搜索框等复杂效果。BottomAppBar则通常用于放置导航项和关键操作,在Material 3设计中还引入了浮动操作按钮(FAB)的集成支持。
2. Scaffold 深度使用指南
2.1 Scaffold 核心参数解析
Scaffold的基本结构包含以下几个关键参数:
kotlin复制Scaffold(
modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
)
提示:scaffoldState应该在整个界面生命周期中保持稳定,不要在重组过程中重新创建
在实际项目中,我通常这样组织基础结构:
kotlin复制val scaffoldState = rememberScaffoldState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = { MyCustomTopAppBar() },
bottomBar = { MyBottomBar() },
floatingActionButton = { MyFAB() },
drawerContent = { MyDrawer() }
) { innerPadding ->
// 主内容区域
Box(modifier = Modifier.padding(innerPadding)) {
MainContent()
}
}
2.2 抽屉导航实现技巧
抽屉导航(Drawer)是Scaffold的重要功能之一。要实现一个功能完整的抽屉,需要注意以下几点:
- 状态管理:使用
rememberDrawerState管理开闭状态 - 手势控制:边缘滑动开启需要正确处理手势冲突
- 内容组织:合理使用Column、LazyColumn等布局组件
- 交互反馈:添加适当的动画和点击效果
典型实现示例:
kotlin复制val drawerState = rememberDrawerState(DrawerValue.Closed)
val gesturesEnabled by remember { derivedStateOf { drawerState.isOpen } }
ModalDrawer(
drawerState = drawerState,
gesturesEnabled = gesturesEnabled,
drawerContent = {
Column(Modifier.fillMaxWidth()) {
DrawerHeader()
Divider()
DrawerItems(items) { item ->
// 处理点击事件
coroutineScope.launch { drawerState.close() }
navigateTo(item.route)
}
}
}
) {
MainContent()
}
注意:在窄屏设备上,ModalDrawer会覆盖内容区域;在宽屏设备上,会变为永久可见的侧边栏
3. TopAppBar 高级应用
3.1 基础TopAppBar实现
Compose提供了三种预设的TopAppBar样式:
- TopAppBar - 标准应用栏
- CenterAlignedTopAppBar - 标题居中的应用栏
- LargeTopAppBar - Material 3风格的大标题应用栏
基础实现示例:
kotlin复制TopAppBar(
title = { Text("我的应用") },
navigationIcon = {
IconButton(onClick = { /* 处理返回或打开抽屉 */ }) {
Icon(Icons.Filled.Menu, contentDescription = null)
}
},
actions = {
IconButton(onClick = { /* 搜索操作 */ }) {
Icon(Icons.Filled.Search, contentDescription = "搜索")
}
IconButton(onClick = { /* 更多操作 */ }) {
Icon(Icons.Filled.MoreVert, contentDescription = "更多")
}
},
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary
)
)
3.2 可折叠TopAppBar实现
实现可折叠效果需要结合CollapsingToolbarLayout的思路,在Compose中可以通过以下方式实现:
- 使用NestedScrollConnection监听滚动位置
- 根据滚动偏移量动态调整TopAppBar高度和内容透明度
- 使用animate*AsState实现平滑过渡
核心代码结构:
kotlin复制val scrollState = rememberLazyListState()
val scrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
// 处理预滚动事件
return Offset.Zero
}
}
}
Box(
modifier = Modifier
.nestedScroll(scrollConnection)
.fillMaxSize()
) {
LazyColumn(state = scrollState) {
// 列表内容
}
val heightRange = with(LocalDensity.current) {
(maxHeight - minHeight).toPx()
}
val height by remember {
derivedStateOf {
if (scrollState.firstVisibleItemIndex > 0) minHeight
else maxHeight - scrollState.firstVisibleItemScrollOffset.coerceAtMost(heightRange)
}
}
TopAppBar(
modifier = Modifier.height(height),
// 其他参数...
)
}
4. BottomAppBar 与 FAB 集成
4.1 基础BottomAppBar实现
BottomAppBar通常包含导航项和少量操作按钮。在Material 3中,BottomAppBar的设计更加简洁:
kotlin复制BottomAppBar(
actions = {
IconButton(onClick = { /* 处理分享 */ }) {
Icon(Icons.Filled.Share, contentDescription = "分享")
}
IconButton(onClick = { /* 处理设置 */ }) {
Icon(Icons.Filled.Settings, contentDescription = "设置")
}
},
floatingActionButton = {
FloatingActionButton(
onClick = { /* FAB操作 */ },
containerColor = BottomAppBarDefaults.bottomAppBarFabColor,
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
) {
Icon(Icons.Filled.Add, contentDescription = "添加")
}
}
)
4.2 FAB位置与形状定制
BottomAppBar允许灵活控制FAB的位置和形状:
kotlin复制BottomAppBar(
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = { /* */ },
icon = { Icon(Icons.Filled.Edit, "编辑") },
text = { Text("新建") },
shape = MaterialTheme.shapes.medium
)
},
floatingActionButtonPosition = FabPosition.Center,
cutoutShape = MaterialTheme.shapes.small,
tonalElevation = 8.dp
)
注意:cutoutShape需要与FAB形状匹配,否则会出现视觉不一致
5. 综合应用与性能优化
5.1 完整页面结构示例
结合所有组件的典型页面实现:
kotlin复制@Composable
fun HomeScreen(
onNavigate: (route: String) -> Unit,
onBack: () -> Unit
) {
val scaffoldState = rememberScaffoldState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
CenterAlignedTopAppBar(
title = { Text("首页") },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(Icons.Filled.ArrowBack, "返回")
}
},
actions = {
IconButton(onClick = { /* */ }) {
Icon(Icons.Filled.Search, "搜索")
}
}
)
},
bottomBar = {
BottomAppBar {
NavigationBarItem(
selected = true,
onClick = { /* */ },
icon = { Icon(Icons.Filled.Home, "首页") }
)
// 其他导航项...
}
},
floatingActionButton = {
FloatingActionButton(onClick = { /* */ }) {
Icon(Icons.Filled.Add, "添加")
}
},
drawerContent = {
DrawerContent { route ->
coroutineScope.launch { scaffoldState.drawerState.close() }
onNavigate(route)
}
}
) { padding ->
LazyColumn(
modifier = Modifier
.padding(padding)
.fillMaxSize(),
contentPadding = PaddingValues(16.dp)
) {
// 页面内容...
}
}
}
5.2 性能优化要点
-
避免不必要的重组:
- 使用
remember缓存计算结果 - 将静态内容提取到单独的可组合函数
- 对列表项使用
key参数
- 使用
-
大型列表优化:
- 使用
LazyColumn/LazyRow替代Column/Row - 合理设置
contentPadding和arrangement - 考虑使用
placeholder处理加载状态
- 使用
-
状态提升:
- 将状态提升到调用方,减少内部状态
- 使用单向数据流架构
-
图像处理:
- 使用
Coil或Glide等专业库加载图片 - 对网络图片使用
placeholder和error处理
- 使用
-
主题管理:
- 使用
MaterialTheme统一管理颜色、形状和排版 - 创建自定义主题扩展函数保持一致性
- 使用
6. 常见问题解决方案
6.1 TopAppBar与状态栏重叠
解决方案:
kotlin复制@Composable
fun TransparentTopAppBar() {
val systemUiController = rememberSystemUiController()
val useDarkIcons = MaterialTheme.colors.isLight
SideEffect {
systemUiController.setStatusBarColor(
color = Color.Transparent,
darkIcons = useDarkIcons
)
}
TopAppBar(
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = Color.Transparent
),
// 其他参数...
)
}
6.2 BottomAppBar遮挡内容
正确处理Scaffold的content padding:
kotlin复制Scaffold(
bottomBar = { /* */ }
) { innerPadding ->
// 确保内容考虑了底部应用栏的高度
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
) {
// 内容...
}
}
6.3 抽屉手势冲突处理
当内容区域有水平滑动组件时,需要特别处理手势冲突:
kotlin复制val drawerState = rememberDrawerState(DrawerValue.Closed)
val scrollState = rememberLazyListState()
ModalDrawer(
drawerState = drawerState,
gesturesEnabled = scrollState.firstVisibleItemIndex == 0
) {
LazyColumn(state = scrollState) {
// 内容...
}
}
6.4 动态改变TopAppBar颜色
根据滚动位置动态改变颜色:
kotlin复制val scrollState = rememberLazyListState()
val color by remember {
derivedStateOf {
if (scrollState.firstVisibleItemIndex > 0 || scrollState.firstVisibleItemScrollOffset > 100) {
MaterialTheme.colorScheme.primary
} else {
Color.Transparent
}
}
}
TopAppBar(
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = color
),
// 其他参数...
)
7. 进阶技巧与设计模式
7.1 多模块共享Scaffold
在大型项目中,可以考虑创建一个基础的Scaffold组件,供各个模块复用:
kotlin复制@Composable
fun AppScaffold(
title: String,
showBackButton: Boolean = false,
actions: @Composable RowScope.() -> Unit = {},
onBack: () -> Unit = {},
content: @Composable (PaddingValues) -> Unit
) {
Scaffold(
topBar = {
TopAppBar(
title = { Text(title) },
navigationIcon = {
if (showBackButton) {
IconButton(onClick = onBack) {
Icon(Icons.Filled.ArrowBack, "返回")
}
}
},
actions = actions
)
}
) { padding ->
content(padding)
}
}
7.2 响应式布局处理
针对不同屏幕尺寸调整布局结构:
kotlin复制@Composable
fun ResponsiveScreen() {
val configuration = LocalConfiguration.current
val isTablet = configuration.screenWidthDp >= 600
if (isTablet) {
TabletLayout()
} else {
PhoneLayout()
}
}
@Composable
fun TabletLayout() {
Row(Modifier.fillMaxSize()) {
NavigationRail {
// 导航项...
}
AppScaffold(
// 参数...
) { padding ->
// 内容...
}
}
}
7.3 主题与动态换肤
实现动态主题切换:
kotlin复制@Composable
fun ThemedApp() {
val isDarkTheme = remember { mutableStateOf(false) }
MaterialTheme(
colorScheme = if (isDarkTheme.value) darkColorScheme() else lightColorScheme(),
typography = AppTypography,
shapes = AppShapes
) {
Scaffold(
topBar = {
TopAppBar(
title = { Text("主题示例") },
actions = {
IconButton(onClick = { isDarkTheme.value = !isDarkTheme.value }) {
Icon(
if (isDarkTheme.value) Icons.Filled.LightMode else Icons.Filled.DarkMode,
"切换主题"
)
}
}
)
}
) { padding ->
// 内容...
}
}
}
7.4 动画与过渡效果
为AppBar添加滚动动画:
kotlin复制@Composable
fun AnimatedAppBar() {
val scrollState = rememberLazyListState()
val elevation by animateDpAsState(
targetValue = if (scrollState.isScrollingUp()) 0.dp else 4.dp,
animationSpec = tween(durationMillis = 300)
)
TopAppBar(
modifier = Modifier.shadow(elevation),
// 其他参数...
)
LazyColumn(state = scrollState) {
// 内容...
}
}
fun LazyListState.isScrollingUp(): Boolean {
return if (firstVisibleItemIndex == 0) {
firstVisibleItemScrollOffset == 0
} else {
firstVisibleItemIndex > 0
}
}
8. 测试与调试技巧
8.1 预览多个设备配置
利用@Preview注解测试不同配置:
kotlin复制@Preview(
name = "Light Theme",
group = "Themes",
showBackground = true,
uiMode = Configuration.UI_MODE_NIGHT_NO
)
@Preview(
name = "Dark Theme",
group = "Themes",
showBackground = true,
uiMode = Configuration.UI_MODE_NIGHT_YES
)
@Preview(
name = "Large Font",
group = "Accessibility",
fontScale = 1.5f
)
@Composable
fun PreviewAppScaffold() {
AppTheme {
AppScaffold(
title = "预览标题",
showBackButton = true
) { padding ->
// 预览内容...
}
}
}
8.2 布局检查与调试
使用Android Studio的Layout Inspector检查Compose布局:
- 运行应用到模拟器或真机
- 点击Android Studio底部的"Layout Inspector"按钮
- 选择正在运行的进程
- 查看Compose组件的层次结构
调试技巧:
- 使用
debugInspectorInfo添加调试信息 - 在组件上添加
Modifier.border()快速查看边界 - 使用
LocalInspectionMode.current检测预览模式
8.3 性能分析
使用Compose专用的性能分析工具:
- 重组计数:添加
Modifier.debugInspectorInfo查看重组情况 - 布局边界:在开发者选项中启用"显示布局边界"
- 性能追踪:使用Android Profiler记录CPU活动
关键性能指标:
- 重组次数
- 跳过重组的次数
- 布局时间
- 绘制时间
9. 兼容性与迁移策略
9.1 与传统View系统共存
在现有项目中逐步引入Compose:
kotlin复制// 在XML布局中添加ComposeView
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
// 在Activity/Fragment中设置内容
findViewById<ComposeView>(R.id.compose_view).setContent {
MaterialTheme {
MyComposeTopAppBar()
}
}
9.2 资源转换指南
将传统资源转换为Compose可用形式:
-
颜色:
kotlin复制// 旧方式 <color name="primary">#6200EE</color> // Compose方式 val primaryColor = Color(0xFF6200EE) -
尺寸:
kotlin复制// 旧方式 <dimen name="padding_medium">16dp</dimen> // Compose方式 val MediumPadding = 16.dp -
字符串:
kotlin复制// 旧方式 <string name="app_name">MyApp</string> // Compose方式 stringResource(R.string.app_name)
9.3 常见迁移问题
-
主题不一致:
- 确保MaterialTheme正确设置
- 使用
LocalContext.current获取正确的资源
-
视图重叠:
- 检查Scaffold的content padding
- 正确处理WindowInsets
-
导航问题:
- 使用
rememberNavController管理导航状态 - 考虑使用
navigation-compose库
- 使用
-
性能下降:
- 检查不必要的重组
- 优化列表性能
- 使用
derivedStateOf减少计算
10. 设计系统集成
10.1 自定义Material组件
扩展MaterialTheme创建设计系统:
kotlin复制@Immutable
data class AppColors(
val brandPrimary: Color,
val brandSecondary: Color,
// 其他自定义颜色...
)
private val LightAppColors = AppColors(
brandPrimary = Color(0xFF0066CC),
brandSecondary = Color(0xFF66A3D2)
// ...
)
private val DarkAppColors = AppColors(
brandPrimary = Color(0xFF3399FF),
brandSecondary = Color(0xFF99C2E0)
// ...
)
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkAppColors else LightAppColors
MaterialTheme(
colorScheme = if (darkTheme) darkColorScheme() else lightColorScheme(),
typography = AppTypography,
shapes = AppShapes,
content = {
CompositionLocalProvider(
LocalAppColors provides colors,
content = content
)
}
)
}
val LocalAppColors = staticCompositionLocalOf { LightAppColors }
10.2 创建自定义AppBar
基于设计规范创建定制组件:
kotlin复制@Composable
fun AppTopBar(
title: String,
modifier: Modifier = Modifier,
navigationIcon: @Composable (() -> Unit)? = null,
actions: @Composable RowScope.() -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val colors = TopAppBarDefaults.centerAlignedTopAppBarColors()
CenterAlignedTopAppBar(
title = {
Text(
text = title,
style = MaterialTheme.typography.titleLarge.copy(
fontWeight = FontWeight.Bold
)
)
},
navigationIcon = navigationIcon,
actions = actions,
colors = colors,
scrollBehavior = scrollBehavior,
modifier = modifier
)
}
10.3 设计令牌(Design Tokens)应用
将设计变量抽象为可复用令牌:
kotlin复制object AppTokens {
val Spacing = object {
val small = 4.dp
val medium = 8.dp
val large = 16.dp
}
val Shapes = object {
val small = RoundedCornerShape(4.dp)
val medium = RoundedCornerShape(8.dp)
val large = RoundedCornerShape(16.dp)
}
val Animation = object {
val short = 150.ms
val medium = 300.ms
val long = 500.ms
}
}
// 使用示例
@Composable
fun TokenExample() {
Column(
modifier = Modifier.padding(AppTokens.Spacing.medium),
verticalArrangement = Arrangement.spacedBy(AppTokens.Spacing.small)
) {
// 内容...
}
}
11. 状态管理与架构模式
11.1 单向数据流实现
将状态提升到ViewModel:
kotlin复制class MainViewModel : ViewModel() {
private val _uiState = mutableStateOf(MainUiState())
val uiState: State<MainUiState> = _uiState
fun onEvent(event: MainEvent) {
when (event) {
is MainEvent.Navigate -> {
_uiState.value = _uiState.value.copy(
currentRoute = event.route
)
}
// 处理其他事件...
}
}
}
@Composable
fun MainScreen(
viewModel: MainViewModel = viewModel()
) {
val uiState = viewModel.uiState.value
Scaffold(
topBar = {
TopAppBar(
title = { Text(uiState.currentRoute.title) },
navigationIcon = { /* ... */ }
)
}
) { padding ->
// 根据uiState显示不同内容...
}
}
11.2 使用Navigation Compose
集成导航组件:
kotlin复制@Composable
fun AppNavigation() {
val navController = rememberNavController()
val currentBackStack by navController.currentBackStackEntryAsState()
val currentRoute = currentBackStack?.destination?.route
Scaffold(
topBar = {
TopAppBar(
title = { Text(currentRoute ?: "首页") },
navigationIcon = {
if (navController.previousBackStackEntry != null) {
IconButton(onClick = { navController.navigateUp() }) {
Icon(Icons.Filled.ArrowBack, "返回")
}
}
}
)
},
bottomBar = {
if (shouldShowBottomBar(currentRoute)) {
BottomNavigation {
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, screen.route) },
label = { Text(screen.route) },
selected = currentRoute == screen.route,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = "home",
modifier = Modifier.padding(innerPadding)
) {
composable("home") { HomeScreen() }
composable("search") { SearchScreen() }
// 其他路由...
}
}
}
11.3 依赖注入实践
使用Hilt进行依赖注入:
kotlin复制@HiltViewModel
class MainViewModel @Inject constructor(
private val repository: MainRepository
) : ViewModel() {
// ...
}
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppTheme {
val viewModel: MainViewModel = viewModel()
MainScreen(viewModel)
}
}
}
}
12. 国际化与无障碍支持
12.1 多语言支持
正确处理字符串资源:
kotlin复制@Composable
fun LocalizedApp() {
val context = LocalContext.current
var language by remember { mutableStateOf(Locale.getDefault().language) }
CompositionLocalProvider(
LocalConfiguration provides Configuration(
LocalConfiguration.current
).apply {
setLocale(Locale(language))
}
) {
MaterialTheme {
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
actions = {
IconButton(onClick = {
language = if (language == "en") "zh" else "en"
}) {
Icon(Icons.Filled.Language, "切换语言")
}
}
)
}
) { padding ->
// 内容...
}
}
}
}
12.2 无障碍支持要点
确保组件可访问:
-
内容描述:
kotlin复制IconButton(onClick = { /* */ }) { Icon( imageVector = Icons.Filled.Menu, contentDescription = "打开导航菜单" ) } -
点击区域大小:
kotlin复制Modifier.sizeIn(minWidth = 48.dp, minHeight = 48.dp) -
焦点顺序:
kotlin复制
Modifier.focusOrder(focusRequester, next = nextFocusRequester) -
文字缩放:
kotlin复制Text( text = "重要信息", style = MaterialTheme.typography.body1.copy( fontSize = 16.sp, lineHeight = 24.sp ) ) -
颜色对比度:
kotlin复制val backgroundColor = MaterialTheme.colorScheme.primary val contentColor = contentColorFor(backgroundColor) TopAppBar( colors = TopAppBarDefaults.topAppBarColors( containerColor = backgroundColor, titleContentColor = contentColor, actionIconContentColor = contentColor ) )
13. 测试策略与实现
13.1 单元测试
测试ViewModel逻辑:
kotlin复制class MainViewModelTest {
@Test
fun `when navigate event received, should update current route`() {
val viewModel = MainViewModel()
val testRoute = "test_route"
viewModel.onEvent(MainEvent.Navigate(testRoute))
assertEquals(testRoute, viewModel.uiState.value.currentRoute)
}
}
13.2 组件测试
使用Compose测试API测试UI组件:
kotlin复制class AppBarTest {
@get:Rule
val rule = createComposeRule()
@Test
fun `should display title in top app bar`() {
val testTitle = "测试标题"
rule.setContent {
MaterialTheme {
TopAppBar(title = { Text(testTitle) })
}
}
rule.onNodeWithText(testTitle).assertExists()
}
}
13.3 端到端测试
使用Espresso测试完整流程:
kotlin复制@RunWith(AndroidJUnit4::class)
class NavigationTest {
@get:Rule
val activityRule = activityScenarioRule<MainActivity>()
@Test
fun `when click bottom nav item, should navigate to correct screen`() {
onView(withContentDescription("搜索")).perform(click())
onView(withText("搜索页面")).check(matches(isDisplayed()))
}
}
14. 发布与优化建议
14.1 性能优化检查清单
发布前的性能检查:
-
重组优化:
- 使用
remember缓存计算结果 - 将静态内容提取到单独函数
- 对列表使用
LazyColumn/LazyRow
- 使用
-
内存管理:
- 检查图像加载内存使用
- 避免在组合函数中创建大对象
-
启动时间:
- 延迟加载非关键组件
- 使用基线配置文件
-
APK大小:
- 启用R8/ProGuard
- 使用资源缩减
14.2 发布配置
正确配置Gradle:
groovy复制android {
defaultConfig {
// 最低支持API级别
minSdk 21
targetSdk 34
// 启用Compose编译器报告
composeOptions {
kotlinCompilerExtensionVersion = "1.5.3"
kotlinCompilerVersion = "1.9.0"
}
}
buildTypes {
release {
// 启用代码缩减和优化
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
// 启用资源缩减
shrinkResources true
}
}
// 启用Compose
buildFeatures {
compose true
}
}
14.3 监控与改进
发布后监控要点:
-
崩溃分析:
- 集成Firebase Crashlytics
- 监控Compose特有崩溃
-
性能指标:
- 帧率稳定性
- 启动时间
- 内存使用
-
用户反馈:
- 收集导航使用数据
- 分析用户交互模式
-
A/B测试:
- 测试不同导航模式
- 评估布局变更效果
