本文译自「From File to Fetch」,原文链接proandroiddev.com/from-file-t...,由Katie Barnett发布于2025年11月23日。

注意 :我与 Airbnb 及其Lottie 项目(Lottie 的 GitHub 仓库)没有任何关联。 我最近刚在一个应用中实现了 Lottie,想分享一些示例来佐证官方文档。
了解 Lottie
之前,我写过关于动画的文章medium.com/bilue/card-...,也在上讨论过这个主题,以及我是如何创建原生动画的。但有时,我们想要一些更具艺术性的效果,不需要移动屏幕上的可组合元素;这时,我们就需要一个预先构建好的动画。
Lottie 就派上用场了。
如果你之前没有使用过 Lottie,它是由 Airbnb 开发人员开发的一个库,可以解析 Adobe After Effects 动画并将其导出为 JSON 格式。其理念是,设计师可以创建复杂的动画,而无需手动渲染。有很多设计工具的插件可以帮助创建动画,例如 Figma。如果你具备一定的设计天赋(我没有!),上手也很容易。
Lottie 已经存在一段时间了,可以在多个平台上渲染,例如 iOS、Web、Windows,当然还有 Android。它可用于 XML 视图,但我今天要重点介绍的是它与 Jetpack Compose 的集成。
官方文档在这里 lottie.airbnb.tech/#/android-c...,但它并没有详细介绍如何使用 LottieCompositionSpec 中的多种不同源类型,以最便捷的方式提供我们的 Lottie 文件。实际上,某些应用可能需要处理多种源类型,尤其是在后端调用中指定特定动画的情况下。
我们将逐步介绍每种类型,但首先,让我们使用字符串来保存 Lottie 动画数据,从而进行基本设置。
字符串来源
使用任何 SDK 的第一步都是添加依赖项:
kotlin
// build.gradle.kts
...
dependencies {
...
implementation(libs.lottie.compose)
}
// libs.version.toml
[versions]
lottie = "6.6.6"
[libraries]
lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" }
然后,在 Composable 中,我们需要创建 LottieCompositionSpec。对于 JSON 字符串,我们可以使用 LottieCompositionSpec.JsonString(val jsonString: String),
并将字符串传递给它。接下来,使用 rememberLottieComposition 并传入 spec 来记住组合状态。最后,可以将此状态传递给 LottieAnimation 以显示动画。
kotlin
val lottieCompositionSpec = LottieCompositionSpec.JsonString(JSON_STRING)
val lottieComposition = rememberLottieComposition(
spec = lottieCompositionSpec
)
LottieAnimation(composition = lottieComposition.value)
const val JSON_STRING = "{\"v\":\"4.10.1\",...\"bm\":0}]}"

现在,将动画存储在字符串中并非最易读或可持续的方式,更好的选择是使用Lottie JSON文件。一种方法是将其存储在assets目录中......
Asset文件
我们可以将Lottie文件存储为.json或.lottie文件(它们是同一种文件,只是扩展名不同),并将其存储在app/assets目录中。

这里唯一的区别是我们需要使用 LottieCompositionSpec.Asset(val assetName: String) 并传递 assets 目录下的路径(你可以根据需要进行组织)。
kotlin
val lottieCompositionSpecLottieFile = LottieCompositionSpec.Asset("animations/android_wave.lottie")
val lottieCompositionSpecJsonFile = LottieCompositionSpec.Asset("animations/android_wave.json")
类似地,我们可以使用 LottieCompositionSpec.File(val fileName: String) 从设备文件系统中的任何位置加载动画文件------只需确保应用程序已获得该文件的访问权限即可!
使用资源文件意味着我们无法获得编译时保护来确保文件存在,但我们可以使用 res/raw 目录。
原始资源文件
同样,这很简单,只需将文件添加到 raw 目录即可:

现在,我们可以通过使用 LottieCompositionSpec.RawRes 和 R.raw 访问原始资源,从而获得编译时安全性。
kotlin
val lottieCompositionSpec = LottieCompositionSpec.RawRes(R.raw.android_wave)
最后,如果我们希望在需要时动态获取 Lottie 文件,而不是将其打包到应用程序中,我们可以从 URL 加载它。
URL 来源
与上述类似,我们可以使用 LottieCompositionSpec.Url 加载以 URL 形式存储的 Lottie 文件:
kotlin
val lottieCompositionSpec = LottieCompositionSpec.Url("https://url/AndroidWave.json")
如果一切顺利,用户网络连接良好,这当然很好,但我们需要确保能够处理任何错误。
错误响应和添加加载状态
动画加载也可能需要一些时间,尤其是在动画文件较大或用户网络连接不佳的情况下。为此,我们可以使用 LottieCompositionResult 来检测动画的状态。
当动画正在下载或解析时,LottieCompositionResult.isLoading 将为 true;当解析成功且合成已准备好显示时,LottieCompositionResult.isSuccess 将为 true。我们还有两个状态:LottieCompositionResult.isComplete,当 isLoading 为 false 时(无论组合是否成功),它将为 true;最后是 LottieCompositionResult.isFailure,当出现不可恢复的错误时(即下文讨论的 onRetry lambda 返回 false 时),它将为 true。
为了展示标准的加载、错误和成功行为,我们可以像这样使用 isLoading 和 isSuccess:
kotlin
if (lottieComposition.isLoading) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.height(100.dp)
) {
CircularProgressIndicator()
}
} else if (lottieComposition.isSuccess) {
LottieAnimation(
composition = lottieComposition.value,
modifier = Modifier.height(100.dp)
)
} else {
Image(
imageVector = Icons.Filled.Error,
contentDescription = null,
modifier = Modifier.height(100.dp)
)
}
重试动画加载错误
Lottie 提供了一种简单易用的方法,可以使用 rememberLottieComposition 中的 onRetry 来重试动画加载。我们可以通过两种方式使用它:
反复重试直到达到某个限制
在构造 rememberLottieComposition 时,我们可以指定 onRetry lambda,并返回 true 以继续重试,返回 false 以停止重试。 onRetry 包含一个 failCount 参数。这允许应用重试次数限制或指数退避。例如:
kotlin
val lottieComposition = rememberLottieComposition(
spec = lottieCompositionSpec,
onRetry = { failCount, exception ->
Timber.d(exception, "Error loading animation: ${exception.message}")
failCount < 5
}
)
这里我将动画设置为重试 5 次后停止。你可以在此 lambda 表达式中添加错误消息或其他任何有用的信息(但请使用上面描述的 LottieCompositionResult.isLoading 布尔值来显示加载行为,而不是在此处设置另一个变量)。

等待重试信号
我们还可以允许动画等待重试,直到某个外部条件发生变化,例如按下按钮或恢复网络连接。
为此,我们使用 rememberLottieRetrySignal。
kotlin
val retrySignal = rememberLottieRetrySignal()
var url by remember { mutableStateOf("https://bad/url") }
val lottieCompositionSpec = LottieCompositionSpec.Url(url)
val lottieComposition = rememberLottieComposition(
spec = lottieCompositionSpec,
onRetry = { _, exception ->
Timber.d(exception, "Error loading animation: ${exception.message}")
retrySignal.awaitRetry()
false
}
)
Column(...) {
if (lottieComposition.isLoading) {
...
} else if (lottieComposition.isSuccess) {
LottieAnimation(
composition = lottieComposition.value,
modifier = Modifier.height(100.dp)
)
} else {
...
}
TextButton(onClick = {
url = "https://url/AndroidWave.json"
retrySignal.retry()
}) {
Text("Fix url & retry")
}
}
在这个简单的示例中,我将 URL 设置为无效 URL,然后在 onRetry 中,当发生错误时,我们可以使用记住的 retrySignal 来等待重试。 retrySignal.awaitRetry()。动画将保持加载状态,直到按钮点击时调用 retrySignal.retry()。如果你不希望保持加载状态,而是希望在重试之前显示错误信息,你可以完全省略 retrySignal,并更新已记住的 url 状态,这样 LottieCompositionSpec 将重新组合。

动画配置
最后,动画加载正确后,我们可以使用一些其他配置项来优化动画效果。
虽然最好在 Lottie 文件本身(创建时完成)中控制这些动画行为,但你也可以通过以下方式调整动画的播放方式: LottieAnimation 本身是可组合的。要了解其功能,最好查看一些可用参数:
kotlin
// An excerpt from version 6.6.6 of the SDK
@Composable
fun LottieAnimation(
clipSpec: LottieClipSpec? = null,
speed: Float = 1f,
iterations: Int = 1,
reverseOnRepeat: Boolean = false,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
... // + others for more advanced use, check out the SDK documentation
) {}
在这里,我们可以控制:
-
clipSpec:动画播放的帧 -
speed:动画速度 -
iterations:动画运行次数(使用LottieConstants.IterateForever可无限循环) -
reverseOnRepeat:循环播放后反向播放 -
alignment和contentScale:就像图像一样,我们可以调整动画在指定范围内的布局。
现在你可以了解 Lottie 的所有用法,请务必为你正在开发的应用程序选择最佳方案,并选择最便捷的方式从你的设计团队获取文件,而无需费力地在不同文件格式之间进行转换。
再见!现在!

你可以在我的 GitHub 仓库的 jc-lottie 模块中找到上述示例代码。
欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!
保护原创,请勿转载!