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

相关推荐
_祝你今天愉快10 小时前
从驱动来分析服务的添加过程
android
Dovis(誓平步青云)13 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
alexhilton14 小时前
让架构边界变成可执行的测试
android·kotlin·android jetpack
hai_android15 小时前
SendChannel 与 ReceiveChannel 通信机制
android
数据治理自习室17 小时前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
爱笑鱼18 小时前
Android 系统启动机制(五):system_server 是 init 启动的,还是 Zygote fork 出来的?
android
智购科技无人售货机工厂19 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
开开心心就好19 小时前
电子教鞭工具支持画框写字插图片功能齐全
android·开发语言·前端·javascript·人工智能·pdf·html
Dovis(誓平步青云)19 小时前
拍视频前先把镜头想清楚:做一个分镜取景辅助器
android·java·服务器·javascript·人工智能
峥嵘life20 小时前
Android16 系统 APEX 模块说明
android·大数据·开发语言