无法将 mutableStateOf(ListOf) 中的项目加载到可组合的 Jetpack Compose 上

问题描述 投票:0回答:1

我正在使用 Kotlin 和 compose 制作一个 Android 应用程序,并使用 GSON 来解析从 API 检索的一些 JSON。然后将数据放入列表中并从函数返回。我有一个可组合项,应该为列表中的每个项目绘制,但返回列表的函数位于协程上。这是我尝试绘制它们的方法,但应用程序崩溃了。

val mutableBricksList = remember { mutableStateOf(listOf<LegoPart>()) }
            Button(onClick = {
                GlobalScope.launch(Dispatchers.IO) {
                    val fetchedLegoBricks =
                        fetchLegoSetBricks("https://rebrickable.com/api/v3/lego/sets/${setNumber}/parts/?key=${BuildConfig.API_KEY}")
                    if (fetchedLegoBricks != null) {
                        withContext(Dispatchers.Main) {
                            mutableBricksList.value = fetchedLegoBricks
                        }
                    }
                }
            }) {
                Text("Load Bricks")
            }

            mutableBricksList.value.forEach { legoPart ->
                Brick(
                    brickNumber = legoPart.part.partNum,
                    brickName = legoPart.part.name,
                    imageURL = legoPart.part.partImgUrl
                )
                println(legoPart.part.name)
            }

如果你想要它,这里是返回列表的函数

suspend fun fetchLegoSetBricks(url: String): List<LegoPart>? = withContext(Dispatchers.IO) {
    val client = OkHttpClient()

    val request = Request.Builder()
        .url(url)
        .build()

    try {
        val response = client.newCall(request).execute()
        val responseBody = response.body?.string()

        // Parse JSON using Gson library
        val gson = Gson()
        val legoResponse = gson.fromJson(responseBody, LegoResponse::class.java)
        val legoPartsList = legoResponse.results

        legoPartsList
    } catch (e: Exception) {
        println("Error fetching LEGO parts: $e")
        null
    }
}

如果您想查看所有代码,该项目位于公共 GitHub 存储库中:https://github.com/IAMGeeCee/BrickBox

我尝试过使用 LaunchedEffect 并让它不在按下按钮时以及在绘制可组合项时使用,但这也不起作用。

android kotlin android-jetpack-compose gson kotlin-coroutines
1个回答
0
投票

您可以发布应用程序崩溃时 logcat 中显示的堆栈跟踪吗?将有助于调试原因。

除此之外,我还发现了一些不正确的用法/可以进行的改进:

  1. val mutableBricksList = remember { mutableStateOf(listOf<LegoPart>()) }
    替换为
    val mutableBricksList = remember { mutableStateListOf<LegoPart>() }
    。然后,您可以通过执行 mutableBricksList.add(...) 来简单地添加到 mutableBricksList

  2. 单击按钮时
  3. 不正确使用

    Globalscope
    。理想情况下,人们不应该花时间在点击监听器中进行操作。相反,只需在视图模型中执行操作并调用视图模型的函数即可。然后,您可以优雅地处理挂起函数,在视图模型内执行耗时操作。

  4. LaunchedEffect(key1=Unit){...}
    应该可以。您能在这里解释一下什么不起作用吗?示例代码将不胜感激。 (无法查看回购协议,抱歉)

  5. 在函数

    fetchLegoSetBricks(..)
    中,理想情况下,不要在每次单击完成时都创建网络客户端。这是资源密集型的。只需在视图模型中创建一次,最好将其作为视图模型的依赖项注入。最佳实践也不是公开网络客户端,而是公开处理任务的用例或存储库(在本例中从 API 获取并解析它)。

  6. MutableStateFlow(..)
    暴露给充当状态持有者的父可组合项,即定义一个数据类,该数据类将保存 API 响应以及 isLoading: Boolean 等其他属性。然后使用推荐的
    <your-state-flow>.collectAsStateWithLifecycle()
    监听此状态流。每当您更新状态流(也称为数据类的属性)时,它都会触发重组,并且您的父可组合项将重新渲染。

希望这对您有帮助。祝您安卓之旅愉快! :)

© www.soinside.com 2019 - 2024. All rights reserved.