patrykandpatrick / vico

A light and extensible chart library for Android.
https://patrykandpatrick.com/vico/wiki
Apache License 2.0
2.08k stars 125 forks source link

Compose Recomposition causing an Error #498

Closed Dimas-Saputra-Me closed 9 months ago

Dimas-Saputra-Me commented 9 months ago

How to reproduce

I'm Using vico 1.13.1 Version and also used Compose as my view style implementation So I was following to use custom axes from the docs, so here is my code somewhat look like. (Is there anything wrong with my code? )

// Graph Data
val context = LocalContext.current
val data = listOf("2022-07-01" to 2f, "2022-07-02" to 6f, "2022-07-04" to 4f).associate { (dateString, yValue) ->
    LocalDate.parse(dateString) to yValue
}
val xValuesToDates = data.keys.associateBy { it.toEpochDay().toFloat() }
val chartEntryModel = entryModelOf(xValuesToDates.keys.zip(data.values, ::entryOf))
val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("d MMM")
val horizontalAxisValueFormatter = AxisValueFormatter<AxisPosition.Horizontal.Bottom> { value, _ ->
    (xValuesToDates[value] ?: LocalDate.ofEpochDay(value.toLong())).format(dateTimeFormatter)
}

// Chart (Placed inside some composable element)
Chart(
    chart = lineChart(context),
    model = chartEntryModel,
    startAxis = rememberStartAxis(),
    bottomAxis = rememberBottomAxis()
)

It does fine at first, untill I add some of things sort like textfield, dropdowns, etc that trigger compose recomposition. Like this for the example

val textState = remember { mutableStateOf("") }
OutlinedTextField(value = textState.value, onValueChange = {textState.value = it})

Whenever I typed in the textfield / trigger recomposition the error cames and crashes the application (This is some of the error code)

FATAL EXCEPTION: main
Process: -, PID: 785
java.lang.IllegalArgumentException: Cannot round NaN value.
 at kotlin.math.MathKt__MathJVMKt.roundToInt(MathJVM.kt:1165)
 at com.patrykandpatrick.vico.core.axis.horizontal.DefaultHorizontalAxisItemPlacer.getLabelValues(DefaultHorizontalAxisItemPlacer.kt:134)
 at com.patrykandpatrick.vico.core.axis.horizontal.HorizontalAxis.drawBehindChart(HorizontalAxis.kt:111)
 at com.patrykandpatrick.vico.core.axis.AxisManager.drawBehindChart(AxisManager.kt:207)
 at com.patrykandpatrick.vico.compose.chart.ChartsKt$ChartImpl$4.invoke(Charts.kt:379)
 at com.patrykandpatrick.vico.compose.chart.ChartsKt$ChartImpl$4.invoke(Charts.kt:307)
 at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:116)
 at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105)
 at androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:86)
 at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:365)
 at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:354)
 at androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw(LayoutModifierNodeCoordinator.kt:182)
 at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:362)

Observed behavior

So here is what I've tried so far

  1. Changing the model using a simple model (Doesn't works) val chartEntryModel = entryModelOf(4f, 12f, 8f, 16f)

  2. Trying to remove my element that trigger recomposition (works) I removed some of my dropdowns and textfield

  3. Changing chart type into columnChart() (Works) Idk why lineChart() does require context as argument but columnChart() doesn't?

    Chart(
    chart = columnChart(),
    model = chartEntryModel,
    startAxis = rememberStartAxis(),
    bottomAxis = rememberBottomAxis()
    )

So that's why I came into the conclusion

  1. There is something wrong in my code, because I implement it in the wrong way or
  2. Compose Recomposition. Because the second and third approach leads into a recomposition (The second one I removed the element who trigger the recomposition and the third one which columnChart() doesn't need context as their argument)

Expected behavior

Thanks in Advance ✨

Vico version(s)

Latest stable version

Android version(s)

11

Additional information

No response

patrickmichalik commented 9 months ago

Hello! It looks like you’re using the wrong lineChart function. The version with a context parameter comes from the views module and shouldn’t be used with Jetpack Compose. Please import and use the composable lineChart function instead.

As such, even though you’re using the wrong function, a crash likely shouldn’t occur here. We’ll look into it. Regardless, switching to the composable function is recommended and should resolve the problem. I’d also like to mention that there’s no longer such a naming clash in Vico 2.

Dimas-Saputra-Me commented 9 months ago

Ah yea I imported the wrong lineChart function. Thanks, it works now. I'll mark it as resolved 👍 Thank you very much

patrickmichalik commented 9 months ago

I’m glad that helped. You’re welcome!