如何在 multi-module、单个 activity、Compose only 项目上显示 Composables 或 ViewModels 的 snackbars

How to show snackbars from Composables or ViewModels on a multi-module, single activity, Compose only, project

在 multi-module 上显示 Snackbar 的最佳方式是什么,单个 activity,只编写项目?

项目依赖关系图如下所示:

项目的唯一 activity 位于 app 模块内,它 just sets the NavHost as content.

将在 NavHost 上显示的每个 feature 模块 provides a list of composable screens

每个屏幕都有 its own Scaffold,因此它可以轻松显示每个屏幕的 ViewModel 的 Snackbar。

有一个特殊的 feature 模块,feature-debug,显示在单个屏幕上,a list of composable provided by each feature module,称为调试部分。它用于允许任何 feature 模块在调试屏幕中自动显示一些设置。

每个调试部分都有自己的 ViewModel,因此它的工作方式与屏幕完全一样。但它缺少脚手架,因为它只占用屏幕的一部分:

+-------------------------+
| Debug screen            |
|-------------------------+
|                         |
| Feature A debug section |
|                         |
|------------------------ +
|                         |
| Feature B debug section |
|                         |
|------------------------ +
|                         |
| Feature C debug section |
|                         |
|------------------------ +
|                         |
| Feature D debug section |
|                         |
+------------------------ +

所以我不确定如何在 feature-debug 屏幕的脚手架上显示 Snackbar,来自另一个 feature 模块内声明的可组合项,该模块不可见任何class 里面 feature-debug.

CompositionLocal可用于通过组合树隐式传递数据。

首先要做的是声明一个必须对提供者和消费者可见的变量(在我的例子中,我在 core-ui 模块中创建了它):

val LocalSnackbarHostState = compositionLocalOf<SnackbarHostState> { error("No SnackbarHostState provided") }

然后提供者应该用 CompositionLocalProvider:

包装它的 children
val scaffoldState = rememberScaffoldState()
    CompositionLocalProvider(
        LocalSnackbarHostState provides scaffoldState.snackbarHostState
    ) {
        Scaffold(
[...]

最后 children 可以获取 SnackbarHostState 的一个实例来访问变量 LocalSnackbarHostState:

val snackbarHostState = LocalSnackbarHostState.current

我只会为您的整个应用程序使用一个 snackbar。它需要包含在 UI 层次结构的根级别,并可通过全局对象访问。这可以通过使用从 Application 继承的 class 并在 class 中放置一个方法来处理显示快餐栏来完成。

有一个示例应用展示了这是如何完成的。演示应用程序可在以下网址下载:

https://github.com/JohannBlake/Jetmagic

当您 运行 应用程序时,打开导航栏和 select 任何导航项。在出现的屏幕上,单击标有 Return value from another screen 的按钮。这将带您到另一个屏幕,您可以在其中 select 一个项目并 return 到上一个屏幕。 selected 项目将显示在小吃栏中。此小吃店在整个应用程序中是全局的。