你写过多少个重复的 @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开发

相关推荐
用户6937175001384几秒前
Android 开发,别只钻技术一亩三分地,也该学点“广度”了
android·前端·后端
唔668 分钟前
原生 Android(Kotlin)仅串口「继承架构」完整案例二
android·开发语言·kotlin
一直都在57220 分钟前
MySQL索引优化
android·数据库·mysql
代码s贝多芬的音符2 小时前
android mlkit 实现仰卧起坐和俯卧撑识别
android
jwn9992 小时前
Laravel9.x核心特性全解析
android
今天又在写代码3 小时前
数据智能分析平台部署服务器
android·服务器·adb
梦里花开知多少4 小时前
深入谈谈Launcher的启动流程
android·架构
jwn9994 小时前
Laravel11.x新特性全解析
android·开发语言·php·laravel
我就是马云飞4 小时前
停更5年后,我为什么重新开始写技术内容了
android·前端·程序员
stevenzqzq5 小时前
Kotlin 协程:withContext 与 async 核心区别与使用场景
android·开发语言·kotlin