Data
CartesianChart
data is stored in CartesianChartModel
s. Just like CartesianChart
s are collections of CartesianLayer
s, CartesianChartModel
s are collections of CartesianLayerModel
s.
CartesianChartModel
s are created via CartesianChartModelProducer
, which works off the main thread. CartesianChartModelProducer
uses Transaction
s. How data is added to a Transaction
depends on the CartesianLayer
(or CartesianLayer
s) in use, so this is covered on the “Column layer” and “Line layer” pages.
Create a CartesianChartModelProducer
instance as follows:
CartesianChartModelProducer.build()
Avoid the unnecessary recreation of CartesianChartModelProducer
s. We recommend instantiating this class in ViewModel
s. If you have to create an instance in a composable function, use remember
. Don’t run data updates by recreating your CartesianChartModelProducer
.
Then, to add and update data, use one of the following:
-
tryRunTransaction
, which is a normal function, attempts to run a data update. The update is rejected if there’s already an update in progress. A boolean indicating whether the update has been accepted is returned. Update processing is fast, so unless you run data updates multiple times per second, and every update must go through,tryRunTransaction
is sufficient.cartesianChartModelProducer.tryRunTransaction { ... }
-
runTransaction
, which is a suspending function, suspends the coroutine from which it’s called until an update can be run. The suspension ends when the update starts being processed.cartesianChartModelProducer.runTransaction { ... }
A
Deferred
implementation is returned, and it is marked as completed once the update has been processed. Thus, to wait until the update has been processed, you can useawait
:cartesianChartModelProducer.runTransaction { ... }.await()
Since CartesianChartModelProducer
handles Transaction
s asynchronously, configuration that depends on the chart data and can change as the data is updated should be performed based on the CartesianChartModel
s and CartesianLayerModel
s passed to callback-based APIs (lambdas and interfaces). Directly using the data from the latest Transaction
may lead to unexpected behavior, as the Transaction
may not have been processed yet. This applies equally to auxiliary data—see “Extras.”
Add a CartesianChartModelProducer
to a CartesianChart
as follows:
- Compose
- Views
CartesianChartHost(modelProducer = cartesianChartModelProducer, ...)
cartesianChartView.modelProducer = cartesianChartModelProducer
Extras
CartesianChartModelProducer
lets you define extras (auxiliary data). These can later be read from model-receiving functions via CartesianChartModel#extraStore
and CartesianLayerModel#extraStore
. Extras are useful for properties that should change with the chart data and that can’t be directly derived from it or should be precalculated. They ensure that the auxiliary data and the chart data remain in sync, given CartesianChartModelProducer
’s asynchronous nature. Solutions such as a Flow
updated each time a Transaction
is commited don’t ensure this synchronization and should thus be avoided. To add extras, use Transaction#updateExtras
. A simple example can be found below. (Don’t worry if you’re not familiar with CartesianValueFormatter
—you’ll learn about it soon.)
val xAxisLabelSuffixKey = ExtraStore.Key<String>()
cartesianChartModelProducer.tryRunTransaction {
updateExtras { it[xAxisLabelSuffixKey] = "km" }
...
}
CartesianValueFormatter<AxisPosition.Horizontal.Bottom> { x, chartValues, _ ->
"$x ${chartValues.model.extraStore[xAxisLabelSuffixKey]}"
}
Use extras only when necessary. The solution above would be needed in instances where the suffix should change with the data. A suffix that never changes or depends on something else wouldn’t benefit from being an extra and could be determined at the formatting stage (in the CartesianValueFormatter
).
Manual CartesianChartModel
creation
We recommend using CartesianChartModelProducer
because it offers performance benefits and animations. However, you can create CartesianChartModel
s manually via the class’s constructor, which takes a list of CartesianLayerModel
s. Since each CartesianLayer
has its own CartesianLayerModel
, you’ll learn how to create CartesianLayerModel
s on the “Column layer” and “Line layer” pages.
CartesianChartModel(...)
Add a CartesianChartModel
to a CartesianChart
as follows:
- Compose
- Views
CartesianChartHost(model = cartesianChartModel, ...)
cartesianChartView.setModel(cartesianChartModel)
When a host receives a CartesianChartModel
, it handles it synchronously, so extras are unneeded here.