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

相关推荐
传奇开心果编程7 分钟前
【Jetpack Compose基础语法学与练】第8课 rememberSaveable,页面旋转/系统重建保留状态
android·学习·ui·kotlin·android jetpack
>Andre<27 分钟前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件
事圆则缓1 小时前
Java 8 Lambda、Stream、Optional 与 Android 边界:从回调语法到运行时兼容
android·java
mmsx1 小时前
Android 地图十万要素不卡顿:空间网格 + 渐进式加载的移动端实践
android·大数据·opengl
Godikov3 小时前
Android 工业终端保活实战:前台服务 + 开机自启 + 更新自启的三重保障
android
字节暗面3 小时前
SO加固强度怎么量化?腾讯ACE与FairGuard静态分析实测
android·逆向
终端安全笔记5 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
字节暗面5 小时前
一次游戏安全SO静态分析记录:腾讯ACE与FairGuard加固强度对比
android·逆向工程·游戏加固
传奇开心果编程5 小时前
【Jetpack Compose基础语法学与练】第9课 SideEffect副作用 + LaunchedEffect,处理异步任务和生命周期
android·学习·ui·kotlin·android jetpack
2401_833269307 小时前
RecyclerView多布局详解
android