你写过多少个重复的 @Preview?Compose 终于要解决这个问题了

打开你的项目,搜一下 MyTheme {

在 Preview 函数里找到了多少个?

10 个?50 个?更多?

每加一个 @Preview,就得手动套一层主题。不套也能跑,但用的是 Material 默认主题------你自定义的颜色、字体、圆角全都不对,看到的不是真机效果。这个烦恼折磨 Compose 开发者三年,Google 终于在这周把修复合并进了 AndroidX 主线。

PreviewWrapper 来了。

问题是什么

Compose 的 @Preview 有个根本性的缺陷:它不知道你的 App 主题。

所以每个 Preview 函数里,你都得自己把内容包进 MyAppTheme {} 里:

kotlin 复制代码
@Preview
@Composable
fun ButtonPreview() {
    MyAppTheme {          // ← 每次都要写
        Surface {         // ← 每次都要写
            MyButton("点我")
        }
    }
}

@Preview
@Composable
fun CardPreview() {
    MyAppTheme {          // ← 又写一遍
        Surface {         // ← 又写一遍
            MyCard()
        }
    }
}

一个组件还好,几十个组件全是这个模式。

更烦的场景是:设计系统升级了,主题初始化方式变了。你要改的不是一处,是全项目所有 Preview 函数。

PreviewWrapper 怎么用

这次合并进 AndroidX 的变更(CL #3950845,已于 2026-03-03 merge 到 androidx-main)引入了两个新 API:

  • PreviewWrapper 接口
  • @PreviewWrapperProvider 注解

用法分三步:

第一步:定义一个 Wrapper

kotlin 复制代码
object MyAppPreviewWrapper : PreviewWrapper {
    @Composable
    override fun WrapContent(content: @Composable () -> Unit) {
        MyAppTheme {
            Surface(color = MaterialTheme.colorScheme.background) {
                content()
            }
        }
    }
}

就是一个实现了 PreviewWrapper 接口的 object,WrapContent 里写你想套的壳。

第二步:创建你自己的 Preview 注解

kotlin 复制代码
@PreviewWrapperProvider(MyAppPreviewWrapper::class)
@Preview
annotation class MyAppPreview

@PreviewWrapperProvider 指向你的 Wrapper,再加上 @Preview,就变成了你的自定义 Preview 注解。

第三步:到处用,再也不重复

kotlin 复制代码
@MyAppPreview
@Composable
fun ButtonPreview() {
    MyButton("点我")   // ← 主题自动套上了
}

@MyAppPreview
@Composable
fun CardPreview() {
    MyCard()           // ← 同样,干净
}

就这样。打开 Android Studio 的 Preview 面板,主题、Surface、背景色,全都在。

和多 Preview 注解配合

很多团队已经在用多 Preview 注解(同时预览多个设备/字号/暗色模式):

kotlin 复制代码
@Preview(name = "Light", uiMode = UI_MODE_NIGHT_NO)
@Preview(name = "Dark", uiMode = UI_MODE_NIGHT_YES)
@Preview(name = "Large Font", fontScale = 1.5f)
annotation class MultiPreview

PreviewWrapper 可以直接和这个组合:

kotlin 复制代码
@PreviewWrapperProvider(MyAppPreviewWrapper::class)
@Preview(name = "Light", uiMode = UI_MODE_NIGHT_NO)
@Preview(name = "Dark", uiMode = UI_MODE_NIGHT_YES)
@Preview(name = "Large Font", fontScale = 1.5f)
annotation class ThemedMultiPreview

一个注解,三种状态,全部带主题。

能做什么,不能做什么

适合用 PreviewWrapper 的场景:

  • 统一注入 App 主题(最常见)
  • 统一加 Surface / 背景色
  • 注入 CompositionLocal(如 LocalDensity、LocalContext mock)
  • 给整个团队统一 Preview 规范

不适合的场景:

  • 运行时逻辑 ------ Wrapper 只在 Android Studio Preview 渲染时生效,发布的 APK 里不存在
  • 替代 @PreviewParameter ------ 后者是提供数据,Wrapper 是提供容器,两者正交,可以同时用

什么时候能用

目前这个 CL 刚合并进 androidx-main(2026-03-03),还没有发布到稳定版。

跟进路径:

  • ui-tooling-preview 的 alpha 版本发布
  • 或者直接用 AndroidX snapshot 版本提前体验

API 已经定型(通过了 API Review +2 和 Code Review),稳定版应该不会有大改动。

为什么这件事值得关注

这不只是少写几行代码的便利改动。

大团队的 Compose 代码库里,Preview 函数往往有几百个。主题不统一、有人忘了套壳、设计更新要全局修改------这些都是真实的管理成本。

PreviewWrapper 把"每个 Preview 函数的规范"变成了"统一定义一次的注解"。这才是重要的地方。


你们项目里有多少个重复的 Preview 包装?到时候能删掉多少行代码?欢迎评论区晒一下。

#JetpackCompose #AndroidDev #Kotlin #Android开发

相关推荐
REDcker2 小时前
Android MediaCodec 架构与实现解析
android·架构
常利兵2 小时前
Android Compose 指南:Column与LazyColumn的抉择
android
黄林晴2 小时前
Kotlin 2.3.20 发布!解构声明不怕写反了
android·kotlin
阿拉斯攀登2 小时前
第 16 篇 摄像头驱动适配,V4L2 子系统详解
android·驱动开发·rk3568·瑞芯微·rk安卓驱动
zklgin2 小时前
MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
android·sql·mysql
牢七2 小时前
baijiacms-master 审计实验
android
刘信的csdn3 小时前
Android Audio模块框架和基础属性概念讲解
android
回到原点的码农3 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
mygljx12 小时前
【MySQL 的 ONLY_FULL_GROUP_BY 模式】
android·数据库·mysql