Home > Enterprise >  Jetpack Compose - Application crashes when clicking on the LazyColumn's item
Jetpack Compose - Application crashes when clicking on the LazyColumn's item

Time:06-09

I recently started coding with Jetpack Compose but now I've ran into issue.

My goal is when clicking on the LazyColumn's item it will navigate and display information on the Detail's Screen.

The code worked well, when I was using normal object. But for my college assigment I needed to get data from Firebase and display it using the MVVM pattern.

Here is my code:

@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)
  }
 }

  }



ViewModel code:

@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
            }
        }
    }

Logs:

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]

Perhaps, filtering the articleResponseisn't a best idea, but I didn't want to provide an additional method to retrieve a single article from Firebase, so filtering was an easier solution. Nevertheless, I would be happy to receive the solution that would allow my idea without getting my application crashed.

CodePudding user response:

You are getting a crash because the response does not include the article you're looking for, and your code assumes it is there.

Change this

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

to

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