Jetpack Compose — 让 Composable 具有生命周期感知能力

981 阅读7分钟

在故事中我们将探索制作 Composable 的不同方法lifecycle-aware。我们还将看到 Composablelifecycle和 View之间的差异lifecycle

image.png

我们将逐步探索不同的解决方案,以便找到一种更好的方法来观察lifecycle“Jetpack Compose-Way”中的可组合事件。

获取页面内容的概览。

页面内容

  • 可组合的lifecycle
  • 视图的lifecycle
  • 可组合的lifecycle与视图的lifecycle
  • 使可组合lifecycle-aware
  • 外卖
  • Github

Composable 的生命周期?

a在此处的lifecycle官方文档中有Composable很好的解释,在这个故事中我将简要介绍一下。

可组合的 lifecycle由以下阶段定义

  • Enter the Composition— 当 Jetpack compose 第一次运行可组合项时,它会跟踪用于描述 UI 的可组合项,并构建所有可组合项的树结构,称为组合。
  • Recomposition— 这是任何状态更改最终影响 UI 的阶段,Jetpack Compose 智能地识别这些可组合项并仅重新组合它们,而无需更新所有可组合项。
  • Leave the Composition— 这是最后一个阶段,当 UI 不再可见时,它会删除所有消耗的资源。

下图(取自官方文档)很好地形象化了这些阶段。

视图的生命周期?

视图lifecycle是任何移动开发及其核心范例中的一个非常基本的概念,许多东西都依赖于 UI 层。它提供对视图不同状态的控制以完成所需的工作。不同的状态是onCreateonStartonPauseonResumeonStoponDestroy

当我们必须对此类事件做出反应时,有不同的用例,lifecycle例如,如果用户从页面移开,那么必须有您可能不再需要的资源,您可以释放它们,或者如果用户从后台转到前台您可能想从后端重新获取最新信息以显示更新的内容等等,此类用例列表还在继续。

Composable 的生命周期与 View 的生命周期

Viewlifecycle和 Composablelifecycle是两种不同的范例。

Jetpack Compose 引入了lifecycle一个Composable与 View 无关的lifecycle. Composablelifecycle是关于创建 UI 组件树结构、跟踪状态更改并提供高效的 UI 更新。而 Viewlifecycle是关于基于用户如何在我们的应用程序/屏幕中进行交互的事件触发,例如移动到另一个屏幕、进入后台、进入前台等。

我们仍然需要使我们的可组合件lifecycle-aware满足许多用例。这意味着我们必须监听 View 的lifecycle事件并对它们做出反应,以最终提供更好的用户体验。

用例

我们希望在用户从后台转到前台时重新获取我们的 App 数据,以从后端获取最新信息并使用最新信息更新 UI。

首先让我们看看代码在没有实现这种行为的情况下看起来如何。

NewsScreen可组合项将使用 显示新闻列表LazyColumn

我们不会进入新闻部分的 UI 实现,并假设它是使用 Jetpack Compose 实现的

正在NewsViewModel初始化时获取数据,如果用户将应用程序移动到后台然后再转到前台,则News不会再次获取数据,因为onResume不会自动创建新协程并且viewModelScope不会执行。launch``fetchNews()

为了实现这种情况,我们必须让我们的 Composable 生命周期感知,观察lifecycle事件以及何时onResume我们必须再次获取News

使可组合生命周期感知?

每个 Composable 都有生命周期所有者LocalLifeCycleOwner.current ,我们将使用它来为 View 的事件添加观察者lifecycle并对它们做出反应。我们还需要确保在 View 销毁并且 Composable 离开 Composition 时移除该观察者。DisposableEffectside-effect API 是这里添加观察者的理想选择,它提供onDispose块以进行清理。

如果您不熟悉DisposableEffectAPI 或想详细探索,我写了一个关于DisposableEffectAPI 的详细故事及其与 的比较LaunchedEffect ,您可以从链接remember(key). 中阅读 ****

下面的代码显示了DisposableEffect添加和删除事件观察器后 API 实现的样子lifecycle

remember让我们将当前事件的代码进一步更新到lifecycle状态变量中lifecycleEvent,并扩展前面的示例以对lifecycle事件做出反应。

在上面的代码中,它记住了一个lifecycleEvent从内部更新的状态变量DisposableEffect。在可组合项中添加NewsScreen了as key 并在is状态时在 lambda 内部调用。这将使Composable 。(代码将保持不变,即公开方法)LaunchedEffect``lifecycleEvent``fetchNews``lifecycleEvent``ON_RESUME``NewsScreen``lifecycle-aware``NewsViewModel``fetchNews

现在,每次 View 进入Resume状态时,它都会再次获取新闻,并且 View 会更新最新内容,以满足我们从后台刷新新闻的用例。

如果需要多个可组合项怎么办lifecycle-aware?然后让我们让此代码可重用于其他可组合项。

让我们看看下面的可重用代码。

可组合项中的代码NewsScreen变得更简单且更易读,因为所有观察lifecycle事件的代码都被移动到一个公共可组合项中,该可组合项在内部记住lifecycle该特定可组合项的状态。NewsScreen只是lifecycle从 Composable 中获取状态rememberLifecycleEvent并将其作为键传递给LaunchedEffect刷新新闻ON_RESUME

这个解决方案有一个问题:  LaunchedEffect不触发 onON_CREATE和第一个ON_START生命周期事件,LaunchedEffect只从ON_RESUME生命周期事件开始监听。也LaunchedEffect意味着运行suspend **与 UI 相关的功能。

一个实际用例是在第一次打开任何屏幕时记录分析事件。为了实现这一点,我们必须监听ON_CREATE事件以记录分析事件,因此我们需要找到一个不同的解决方案来对ON_START/ON_CREATE生命周期事件做出反应。

我们将使用DisposableEffectAPI 来监听lifecycle事件并在 API 效果块中对它们做出反应DisposableEffect。我们还希望使解决方案可重用,以便将其合并到其他可组合项中。

让我们看看下面的代码

DisposableEffectWithLifecycle``lifecyclecomposable 为所有事件、观察者事件获取 lambda 参数lifecycle,并对每个事件执行特定方法lifecycle。封装离开 Composition 时的DisposableEffectWithLifecycle观察事件和清理。lifecycle它是可重用的解决方案,可以轻松地集成到任何其他可组合项中,使可组合项具有生命周期感知能力。

ON_CREATE它解决了我们的问题,并ON_START在我们之前的解决方案失败的地方提供了事件。

这是一个合理的解决方案,但我们甚至可以更好地将此类代码移动到 ViewModel 中,我们的 ViewModel 将在其中观察事件lifecycle并做出反应。

使 ViewModel 生命周期感知

要创建 ViewModellifecycle-aware并监听lifecycle特定可组合项的事件,我们必须将可组合项传递lifecycleOwner给 ViewModel。

为此,我们将为 ViewModel 编写一个扩展的 Composable 函数,它将接收 Composable lifecycle OwnerLocalLifecycleOwner.current.lifecycle并将在onDispose块上添加观察者和移除观察者。ViewModel 将实施DefaultLifecycleObserver并开始接收lifecycle事件。然后在OnResume生命周期事件上它将调用fetchNews()方法。

让我们在下面的代码中看到所有内容。

ViewModel 正在观察事件变化并对其做出反应。

业务逻辑被移至 ViewModel,您可以在特定生命周期状态下测试 ViewModel 并检查该状态的结果。此外,我们在 UI 中的代码更少,在 ViewModel 中的方法也更少。

外卖

  • Composablelifecycle和 Viewlifecycle是两个不同的概念。
  • 每个 Composable 都有生命周期所有者LocalLifeCycleOwner.current ,我们可以使用它来为 View 的lifecycle事件添加观察者
  • DisposableEffect提供在 上观察和清理观察者的方法onDispose
  • LaunchedEffect不接收ON_CREATE和第一个ON_START事件。
  • 始终最小化您的 UI 代码。

关注公众号:Android老皮
解锁  《Android十大板块文档》 ,让学习更贴近未来实战。已形成PDF版

内容如下

1.Android车载应用开发系统学习指南(附项目实战)
2.Android Framework学习指南,助力成为系统级开发高手
3.2023最新Android中高级面试题汇总+解析,告别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到精通,构建高质量UI界面
6.Flutter技术解析与实战,跨平台首要之选
7.Kotlin从入门到实战,全方面提升架构基础
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 性能优化实战+360°全方面性能调优
10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔