CartesianChartModelProducer
A chart’s data is stored in its model, represented by CartesianChartModel. Much like CartesianChart combines CartesianLayer instances, CartesianChartModel combines CartesianLayerModel instances. Use the transaction-based CartesianChartModelProducer to create models.
Creation
Instantiate CartesianChartModelProducer via the constructor. Since data updates are performed via transactions, the producer used by a chart shouldn’t be replaced. Thus, store it in a place with sufficient persistence, such as a view model.
Transaction
TransactionUse runTransaction to perform an update in a transaction. This is a suspending function:
cartesianChartModelProducer.runTransaction { /* ... */ }This function returns when the update is complete—that is, once a new model has been generated, and the host has been notified. If there’s already an update in progress, the current coroutine is first suspended until the ongoing update’s completion.
How data is added in a transaction depends on the layers in use, so we cover this later, on the pages that describe the individual CartesianLayer implementations.
Asynchrony
runTransaction works off the main thread, meaning that model generation and processing happen asynchronously. Moreover, during an update, two models may be dealt with at once—one in the foreground and one in the background. Thus, dynamic setup tied to model updates should be performed based on Vico-provided arguments of lambdas, interface functions, and the like. These functions may receive CartesianChartModel instances or related data. For such setup, external mechanisms should be avoided:
Never directly use the data from the latest transaction.
Never introduce a separate channel that makes setup changes as a transaction runs.
These solutions don’t have the tight coupling with the transaction mechanism that synchronization requires and may thus produce improper, unpredictable results.
For setup derived from series data, the correct, argument-based approach is straightforward, with the data being readily available in the model and its ranges. Functions may receive these directly, but they’re usually accessed via CartesianMeasuringContext and its subtypes; see CartesianMeasuringContext.model and CartesianMeasuringContext.ranges.
However, changes that aren’t directly derived from series data may also need to be aligned with model updates. We thus need a means of sending additional information through the same channel that’s used for series data. This is where extras, described in the following subsection, come in.
Extras
Extras are a means of adding auxiliary data to models. They’re stored in CartesianChartModel.extraStore and use typed keys (ExtraStore.Key instances), enabling you to save any kind of data in a type-safe manner. To add extras, use Transaction.extras, as shown below. (This is, of course, a simplified example. Extras are used for values that change; static values don’t require synchronization.)
Just like series data, extras can be accessed via function arguments. In ExtraStore-focused contexts, an ExtraStore instance is provided explicitly. Where this isn’t the case, use CartesianChartModel.extraStore, obtaining the model as described above. (That’s context.model.extraStore in most cases.)
Extras are read like Map elements. Assume you have an ExtraStore reference called extraStore and an ExtraStore.Key reference called Key. If the extra is added on every transaction, use the following:
If the extra is added conditionally, meaning that it may not be present, use this:
ExtraStore.Key instances are compared by identity. Given the asynchronous context in which they’re used, it’s important not to recreate or swap them more often than appropriate. Ensure the following:
Each
ExtraStore.Keyinstance used with a particular model producer is persisted at least as long as the correspondingCartesianChartModelProducerinstance. (A universal approach is to store keys statically—at the top level, in companion objects, and so on. This can also make your code more elegant, eliminating the need for passing key references around.)A property’s
ExtraStore.Keyinstance remains unchanged throughout the lifetime of the associated model producer.
See the following sample charts for examples of extra usage:
Manual CartesianChartModel creation
CartesianChartModel creationUsing CartesianChartModelProducer is recommended because it offers performance benefits and supports animations. However, you can create models manually via the CartesianChartModel constructor, which takes a list of CartesianLayerModel instances. When a host receives such a model, it handles it synchronously. Any asynchronous processing is explicitly handled by the consumer. Thus, extras are unneeded.
Sample charts
Last updated