如何在 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 项目将显示在小吃栏中。此小吃店在整个应用程序中是全局的。
在 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
:
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 项目将显示在小吃栏中。此小吃店在整个应用程序中是全局的。