我最近开始使用Jetpack Compose进行编码,但现在遇到了问题.

我的目标是,当单击LazyColumn的项目时,它将导航并在详细信息屏幕上显示信息.

当我使用普通对象时,代码运行得很好.但对于我的大学助理,我需要从Firebase获取数据,并使用MVVM模式显示它.

这是我的代码:

@Composable
fun DetailsUI(navController: NavController, articleId: String?,viewModel: ArticleViewModel = hiltViewModel()) {
 var expanded = remember { mutableStateOf(false) }
 val articleResponse = viewModel.articleState.value

 Scaffold(
 ) {
  when (articleResponse) {
   is Loading -> ProgressBar()
   is Success ->Column(){
    var newArticle = articleResponse.data.filter { article -> //the problem area that logs indicated
     article.id==articleId
    }
       ArticleHeader(image =newArticle[0].image)
       ArticleTitle(title =newArticle[0].title , author = newArticle[0].author )
       ArticleContent(content =newArticle[0].title )

     }




   is Error -> Utils.printError(articleResponse.message)
  }
 }

  }



视图模型代码:

@HiltViewModel
class ArticleViewModel @Inject constructor(
    private val useCases: UseCases
):ViewModel() {
    private val _articleState = mutableStateOf<Response<List<Article>>>(Response.Loading)
    val articleState: State<Response<List<Article>>> = _articleState

    init {
        getArticles()
    }

    private fun getArticles() {
        viewModelScope.launch {
            useCases.getArticle().collect { response ->
                _articleState.value = response
            }
        }
    }

日志(log):

2022-06-09 00:43:35.248 12215-12215/com.example.flow E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.flow, PID: 12215
    java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
        at java.util.ArrayList.get(ArrayList.java:437)
        at com.example.flow.DetailScreenKt$DetailsUI$2.invoke(DetailScreen.kt:99)
        at com.example.flow.DetailScreenKt$DetailsUI$2.invoke(DetailScreen.kt:92)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
        at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
        at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
        at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2158)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2404)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2585)
        at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2571)
        at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:247)
        at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2571)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2547)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:620)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:786)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:105)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:456)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:425)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:947)
        at android.view.Choreographer.doCallbacks(Choreographer.java:761)
        at android.view.Choreographer.doFrame(Choreographer.java:693)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@dde2781, StandaloneCoroutine{Cancelling}@6665026, AndroidUiDispatcher@95fe467]

也许,过滤articleResponse不是一个好主意,但我不想提供从Firebase检索单个文章的额外方法,因此过滤是一个更简单的解决方案.尽管如此,我还是很高兴收到这样的解决方案,它将允许我的 idea ,而不会使我的应用程序崩溃.

推荐答案

您会遇到崩溃,因为响应中不包含您要查找的文章,并且您的代码假定它在那里.

更改此

var newArticle = articleResponse.data.filter {       
    article.id==articleId
}

val newArticle = articleResponse.data.firstOrNull {       
    article.id==articleId
}
if (newArticle != null) {
    // display article
} else {
    // display Article not found error
}

Kotlin相关问答推荐

在Kotlin中求n个ClosedRange实例相交的最常用方法是什么?

CompositionLocal 究竟如何以及何时隐式设置值?

在 Kotlin 中将 Array 转换为 IntArray 时丢失值

为什么可组合对象看似无状态(唯一传递的参数是函数,而不是状态),但会进行重组

如何使用 Kotlin Maven 更改 Minecraft 插件中的 Shulker GUI 标题

Spring Boot Kotlin 数据类未使用 REST 控制器中的默认值初始化

使用 StateFlow 时如何移除监听器?

Kotlin 启动与启动(Dispatchers.Default)

如何在 Android Jetpack Compose 中的画布上绘制一侧加厚的描边?

Jetpack Compose - 单击 LazyColumn 的项目时应用程序崩溃

Dagger 2 ContributesAndroidInjector 为模块提供活动

Kotlin 语言是如何用 Kotlin 编写的?

如何用 kotlin 打包 List

如何在顶级函数中使用 koin 注入依赖项

kotlin:扩展方法和空接收器

有没有办法在数据类构建时转换属性的值?

Java Integer.MAX_VALUE 与 Kotlin Int.MAX_VALUE

如何序列化/反序列化Kotlin密封类?

lateinit 的 isInitialized 属性在伴随对象中不起作用

在多平台子元素中使用kapt