处理丢失的渲染上下文(Handling a lost render context)
渲染上下文是 Rive worker 用来渲染的 GPU 设备(Vulkan)或 GPU 上下文(OpenGL)。GPU 驱动重置或失败时,它可能丢失。之后,该 worker 上的 Rive 实例会停止更新。worker 不会自行恢复,因此应用需要替换它。
检测丢失的渲染上下文(Detecting a lost render context)
从 v11.16.0 起,可以用 RiveWorker.renderContextStatus 检测丢失的渲染上下文。这个 StateFlow 一开始是 RenderContextStatus.Ready,当 Rive 检测到丢失时变为 RenderContextStatus.Lost。它不会再变回去。
Rive 在 worker 下一次绘制时检测丢失,并在 worker 被轮询时更新状态。生命周期处于 resumed 时,rememberRiveWorker 和 rememberRiveWorkerOrNull 默认会为你轮询 worker。如果你自己创建 RiveWorker,需要调用 beginPolling。
Ready 只表示 Rive 还没有检测到丢失。它不表示 worker 上的每个操作都会成功,因此仍要处理 Rive API 可能抛出的错误。Rive 也可能漏掉某些丢失,例如第一次出现在它所绘制的 surface 正在创建或调整大小时的丢失。
用新的 worker 恢复(Recovering with a new worker)
要恢复,请创建一个新的 worker,并在上面重新加载内容。如果你用 RiveWorker 构造函数创建 worker,请自己释放丢失的 worker。同时关闭你在没有 remember 函数的情况下从它加载的任何东西,例如文件和图像。旧 worker 只有在被释放、且从它加载的一切都已关闭之后才会关闭。
在 Compose 中恢复(Recovering in Compose)
参见 Compose 渲染上下文恢复示例,其中由 Android ViewModel 持有 worker。
你可以把 worker 以及从它加载的一切放进一个 key 块,并在状态变为 Lost 时更改这个 key。key 变化时,Compose 会销毁该块。其中的 remember 函数会关闭它们加载的内容并释放旧 worker。然后该块会用新的 worker 再次运行。
创建新 worker 可能失败,因此下面的示例使用 rememberRiveWorkerOrNull。它返回 null 而不是抛出异常,这样你可以显示后备界面。
setContent {
var workerGeneration by remember { mutableIntStateOf(0) }
key(workerGeneration) {
val errorState = remember { mutableStateOf<Throwable?>(null) }
val riveWorker = rememberRiveWorkerOrNull(errorState)
if (riveWorker == null) {
// Show a fallback. Changing workerGeneration tries again.
ErrorMessage(errorState.value)
} else {
LaunchedEffect(riveWorker) {
// Waits until the worker loses its render context.
riveWorker.renderContextStatus.first { it == RenderContextStatus.Lost }
workerGeneration++
}
val riveFile = rememberRiveFile(
RiveFileSource.RawRes.from(R.raw.my_rive_file),
riveWorker
)
when (riveFile) {
is Result.Loading -> LoadingIndicator()
is Result.Error -> /* Handle the error */
is Result.Success -> Rive(riveFile.value)
}
}
}
}
用 RiveCanvasSession 恢复(Recovering with RiveCanvasSession)
实验性的 RiveCanvasSession 在丢失后会停止推进和渲染,但 beginPlaying 在你关闭会话或取消其协程之前不会返回。请自己观察 renderContextStatus,然后关闭会话以及你加载的内容,并在新的 worker 上重新创建它们。参见 Canvas 渲染上下文恢复示例。
重新加载资源(Loading assets again)
嵌入 Rive 文件中的资源会随文件再次加载。你自己加载的图像、字体和音频只能在加载它们的那个 worker 上使用,因此要在新的 worker 上重新加载。保留它们的字节,或准备好再次下载。
恢复状态(Restoring state)
新 worker 上的一切都从初始状态开始。状态机从入口状态开始,新的视图模型实例具有初始值。如果你的应用更改过视图模型属性,请在新的视图模型实例上再次设置它们。再次设置只会在状态机的过渡使用这些属性时改变其状态。