当前位置: 首页 > 知识库问答 >
问题:

多状态喷气背包组成屏幕

方英耀
2023-03-14

我的屏幕应该显示三件事之一:(我对Jetpack Compose也很陌生)

一个 Loader() 如果加载 一个 AlertDialog() 如果有错误 最后,基于我的视图模型中的一个 int,一个新的 ScreenX()

我在视图模型中进行了 API 调用,并相应地更新了 3 个状态变量。问题在于,所有视图似乎都出现在彼此之上。

如果我尝试返回 Loader(),我会收到一个错误。

也许这不是正确的方法,但是有什么方法可以在可组合对象中使用动态屏幕吗?

@Composable
fun ConnectionScreen(
    ip: String,
    viewModel: BridgeViewModel,
    navController: NavHostController
) {
    val page = viewModel.page.collectAsState()
    val loading = viewModel.loading.collectAsState()
    val error = viewModel.error.collectAsState()

    Scaffold {
        if (loading.value) {
            Loader()
        }

        error.value?.let {
            AlertDialogWithButtons(
                title = "Error",
                message = it,
                onNegativeClick = { },
                onPositiveClick = {},
            )
        }

        when (page.value) {
            0 -> Screen0() 
            1 -> Screen1() 
            2 -> Screen2()
        }
    }
}

共有2个答案

金子平
2023-03-14

我决定创建一个封装数据类来更好地表示 UI 状态。它不是最好的,不幸的是不可重用(我需要为每个屏幕创建一个新的数据类?即使大多数将使用API,因此加载和错误应该是可重用的)。

enum class ResourceState { LOADING, ERROR, LINK, FINISH }

data class CreateResourceState(
    val loading: Boolean = false,
    val error: String? = null,
    val page: Int = 0,
) {
    val state: ResourceState
        get() {
            return if (loading) ResourceState.LOADING
            else if (error != null) ResourceState.ERROR
            else if (page == 1) ResourceState.LINK
            else if (page == 2) ResourceState.FINISH
            else ResourceState.LOADING
        }
}

然后在我的观点模型中

private val _uiState = MutableStateFlow(CreateResourceState(loading = true))
val uiState: StateFlow<CreateResourceState> = _uiState

...

_uiState.value = CreateResourceState(error = exception.message)

...

_uiState.value = CreateResourceState(page = 1)

最后在用户界面中

val uiState = viewModel.uiState.collectAsState()

when (uiState.value.state) {
    ResourceState.LOADING -> Loader()
    ResourceState.ERROR -> ErrorDialog()
    ResourceState.LINK -> Screen1()
    ResourceState.FINISH -> Screen2()
}

对我来说,您只能返回一个且只能返回一个可组合项似乎仍然很奇怪。也许我太习惯了 Flutter,您可以在另一个 Widget 中随时动态返回任何 Widget。

容学林
2023-03-14

有这个错误(我很确定我们可以这样称呼它,因为它会崩溃整个应用程序并显示无意义的错误消息),您无法从可组合布局中的 lambda 内部返回。因此,如果您这样做:

Column {
  if (variable){
    return 
  }
  Text("test")
}

如果变量为 true,则编写硬崩溃。我正在尝试查找是否有错误报告。同时 - 您可以采取 2 件事来避免这种情况:

您可以移动代码以使其正常运行,如下所示:

@Composable
fun ConnectionScreen(
    ip: String,
    viewModel: BridgeViewModel,
    navController: NavHostController
) {
    Scaffold {
        Content(viewModel)
    }
}

@Composable
fun Content(viewModel: BridgeViewModel) {
    val page = viewModel.page.collectAsState()
    val loading = viewModel.loading.collectAsState()
    val error = viewModel.error.collectAsState()
    if (loading.value) {
            Loader()
        }

        error.value?.let {
            AlertDialogWithButtons(
                title = "Error",
                message = it,
                onNegativeClick = { },
                onPositiveClick = {},
            )
        }

        when (page.value) {
            0 -> Screen0() 
            1 -> Screen1() 
            2 -> Screen2()
        }
{

或者你可以坚持if-else,就像这样:

@Composable
fun ConnectionScreen(
    ip: String,
    viewModel: BridgeViewModel,
    navController: NavHostController
) {
    val page = viewModel.page.collectAsState()
    val loading = viewModel.loading.collectAsState()
    val error = viewModel.error.collectAsState()

    Scaffold {
        if (loading.value) {
            Loader()
        } else {
            error.value?.let {
                AlertDialogWithButtons(
                    title = "Error",
                    message = it,
                    onNegativeClick = { },
                    onPositiveClick = {},
                )
            }

            when (page.value) {
                0 -> Screen0() 
                1 -> Screen1() 
                2 -> Screen2()
            }
        }
    }
}
 类似资料:
  • 可以在Jetpack Compose中进行权重吗?例如,我想以这样一种方式设置它,即一个项目被加权为布局的1/3,而另一个占剩余的2/3。 在XML/ViewGroup样式中,可以使用LinearLayouts和ConstraintLayouts来实现这一点。然而,令我沮丧的是,使用Jetpack Compose似乎是不可能的。 示例: 在ConstraintLayout中,这是按如下方式完成的:

  • 我有一个包含多个< code>LazyRow的< code>LazyColumn。在旧术语中,嵌套RecyclerView。 我的问题是,当移动到一个新的可组合(不同的选项卡)时,不会恢复滚动状态。但是内部s恢复它们的状态。 例如,打开主屏幕,滚动到底部,然后滚动结束,然后打开不同的选项卡并再次返回主选项卡。 的产品进行评级 如何恢复滚动状态?

  • 如何从下方显示惰性列?默认情况下,它显示上面的列表

  • 几天来,我一直试图成功地构建我正在进行的项目(使用Jetpack Compose),但当我更新gradle构建插件和其他一些依赖项时,我无法正确运行该项目。有一些gradle版本与dagger-hilt依赖项冲突,我不知道如何修复它。我正在使用Android Studio的金丝雀测试版。 这里还有我所有的gradle构建文件: Gradle构建模块应用程序: Gradle构建(项目层级): 错误:

  • 我想根据条件更改我的开始导航片段。我的起始片段可以是片段1或片段2。有没有办法实现它?

  • 我想知道什么是喷气背包中的脚手架组成一个BottomAppBar示例任何人都可以帮我

  • 我创建了一个项目,并添加了插件和dependency,我还对其进行了测试,结果很好。但当我重构项目以使用并启用jetifier工具项目不会构建,我会遇到多个错误,如: 转换文件“crashlytics-2.9.2.aar”以匹配属性{artifactType=jetitied-aar}失败 似乎< code>jetifier工具和< code>Crashlytics依赖项有问题。有没有办法关闭单个

  • 我在jetpack compose中确实有一个要求,即我的脚手架中需要一个底部杆,也需要一个高度可调的底部板。我只能实现其中的任何一个。我不得不用下面的代码牺牲底部的条: 我没有选择在这里使用底部栏,而我可以自由调整纸张的高度。第二种解决方案是使用ModalBottomSheetLayout,我可以在其中添加脚手架并添加底部栏,但无法调整板材的高度。