Skip to main content

Version 0.15.0

Two things need migration work in this release:
  • Data Binding binds when you create a RiveWidgetController, and the separate dataBind call is removed.
  • The Rive Renderer (Factory.rive) uses deferred rendering on native platforms. This only affects advanced integrations.
0.15.0 is a dev release (0.15.0-dev.2). Migrate against the APIs below, but expect changes before the stable release.

Requirements

The minimum Flutter version is 3.32.0 (Dart 3.8.0). Version 0.14.x declared 3.28.0 by mistake, so older Flutter versions resolved the package and then failed to compile. See rive-flutter issue #643.

Data Binding

Binding happens at construction

RiveWidgetController binds when you construct it. The Artboard’s main View Model, and every global View Model in the file, receive a default instance unless you choose otherwise with the new main and globals parameters:
On content without Data Binding, the bind is a no-op.
Behavior change: content with View Models that previously rendered unbound now renders its authored default values, because construction binds automatically.
Read bound instances back through controller.viewModelInstance and controller.globalViewModelInstance(name). Both are live reads that return the same object every time. To rebind later, call controller.bind(main: ..., globals: {...}). Each call applies as a delta on the current bindings. Anything you leave out keeps the instance it already has, and however many slots you set, the rebind runs once. Debug builds warn once when bind runs before the controller’s first advance, since the construction bind is then discarded before anything rendered. Pass the configuration to the constructor instead.

Removed APIs

Legacy bridge

To keep existing call sites compiling while you migrate:
This restores controller.dataBind and RiveLoaded.viewModelInstance as deprecated extensions. The old ownership contract comes with them, so you dispose what dataBind returns. The library is frozen and will be removed in a future release, so treat the import as a migration TODO.

Instance ownership

The controller owns every instance it resolves for you (DataBind.auto, byName, byIndex, and empty) and disposes them with itself. Drop any manual dispose call for those. Instances you create and pass with DataBind.byInstance are never disposed by the runtime. RiveWidgetBuilder no longer disposes them either, so a caller-owned instance now survives the widget. If you kept an instance in use past its controller, create it yourself and bind it by instance:

Read-backs cannot be bound again

controller.viewModelInstance and controller.globalViewModelInstance(name) return plain ViewModelInstance views. Read, write, and listen to them as usual, but you cannot pass one to DataBind.byInstance. That takes only a BindableViewModelInstance, which is what ViewModel.createInstance and its siblings return. Passing a read-back is a compile error, and forcing it with a cast throws at runtime. Create your own instance to share state across slots or controllers.

Deferred rendering

The Rive Renderer (Factory.rive) now uses deferred rendering on native platforms, and it is the only native rendering mode. Each frame is recorded on the UI thread as a compact command stream and replayed on a dedicated render thread, so GPU work no longer blocks the UI thread. Resources made with Factory.rive (paths, paints, images, text) are lightweight recording proxies that resolve during replay.
Rendering behavior and output are unchanged for typical RiveWidget, RivePanel, and file-based usage. The items below only affect advanced integrations. Factory.flutter is unaffected.

Threading

All Rive calls stay on the calling (UI) thread. The command stream has a single writer per frame, so advancing or drawing from other threads is not supported. Doing so corrupts the stream, visible as rive replay ABORT messages in the console.

Removed batch advance API

Breaking: Rive.batchAdvance and Rive.batchAdvanceAndRender have been removed, along with the Rive class that held them. Their worker threads recorded into the single-writer command stream concurrently and corrupted it. Advance and draw each State Machine on the calling thread instead:
For Rive.batchAdvanceAndRender, draw each Artboard on the calling thread after advancing its State Machine, as before.

Custom render texture painters

RenderTexturePainter.riveFactory names the factory the painted content was made with, so the texture can attach its recording session. A sessionless texture draws nothing on native, with a one-time console warning: texture has no deferred session, nothing will draw. The getter defaults to Factory.rive, which is correct for content decoded and created on it, so most custom painters need no change. Override it with the decoded file’s File.riveFactory when content records elsewhere, or with null when you manage the texture’s session yourself. On web, sessions are per file and bound to one texture. The content-derived override therefore applies only to single-file content, where it opts the texture into the per-file session worker path. A painter drawing multiple files into one texture keeps the default and renders through the immediate fallback. SharedTexturePainter adds a riveFactory getter (default null) for the same reason on the RivePanel paint pass. A class that implements SharedTexturePainter must add the getter. A class that extends it inherits the default.

One Artboard instance per texture

Showing the same Artboard instance in two RiveWidgets leaves the later widget blank and logs a debug message. Create one Artboard instance per widget, for example with file.artboard('MyArtboard') for each widget.

Factory.rive and the recording session

On native platforms, Factory.rive resolves to the render context’s recording session. file.riveFactory == Factory.rive still holds, and resources created directly on Factory.rive record and render correctly.

Advanced session control

package:rive_native/rive_deferred.dart exposes manual session control: attaching or detaching a texture’s session with RenderTexture.useDeferredSession, session helpers, and render thread stats. Typical apps do not need it.

Version 0.14.0

This is a significant update for Rive Flutter. We’ve completely removed all of the Dart code that was used for the Rive runtime and replaced it with our underlying C++ Runtime. See the Rive Native for Flutter page for more details. This has resulted in a number of changes to the underlying API, and a large portion of the code base that was previously accessible through Dart is now implemented in C++ through FFI.

What’s new in 0.14.0

This release of Rive Flutter adds support for: Now that Rive Flutter makes use of the core Rive C++ runtime, you can expect new Rive features to be supported sooner for Rive Flutter.
All your Rive graphics will still look and function the same as they did before.

Requirements

Dart and Flutter versions

This release bumps to these versions:

Required setup

Important: You must call RiveNative.init at the start of your app, or before you use Rive. For example, in main.dart:

Migration guide

Quick migration checklist

  1. ✅ Update your pubspec.yaml dependencies to use version 0.14.0 or later
  2. ✅ Add RiveNative.init() to your main() function, or call before using Rive.
  3. ✅ Replace Rive and RiveAnimation widgets with RiveWidget or RiveWidgetBuilder
  4. ✅ Update your controllers to use the new API, see RiveWidgetController
  5. ✅ Review and update any custom asset loading code
  6. ✅ Test your graphics and interactions

Removed classes

The following classes have been completely removed:
  • Rive and RiveAnimation widgets → Use RiveWidget and RiveWidgetBuilder
  • RiveAnimationController and its subclasses → Use RiveWidgetController, SingleAnimationPainter, and StateMachinePainter
  • OneShotAnimation and SimpleAnimation → Use SingleAnimationPainter to play individual animations
  • StateMachineController → Use StateMachine instead (can be accessed via RiveWidgetController.stateMachine)
  • RiveEvent → Replaced with Event
  • SMITrigger → Replaced with TriggerInput
  • SMIBool → Replaced with BooleanInput
  • SMINumber → Replaced with NumberInput
  • FileAssetLoader → Replaced with optional callback when creating a File

Loading Rive files

RiveFile has been removed and replaced with File. Important changes:
The provided Factory determines the renderer that will be used. Use Factory.rive for the Rive renderer or Factory.flutter for the shipped Flutter renderer (Skia or Impeller).
Vector Feathering only works with the Rive Renderer.
Key Changes:
  • Creating a Rive File now requires a factory (Factory.rive or Factory.flutter)
  • Replace RiveFile.import with File.decode() which returns a Future<File>
  • Replace mainArtboard with defaultArtboard()
  • Replace artboardByName(name) with artboard(name)
  • Replace RiveFile.network with File.url
  • Replace RiveFile.file with File.path

Widget migration

See the updated example app for a complete migration guide, including how to use the new RiveWidget and RiveWidgetBuilder APIs.
Using RiveWidgetBuilder

Controller migration

Example using the new RiveWidgetController:
Using RiveWidgetController
Optionally specify which Artboard and State Machine to use:
Specifying Artboard and State Machine

Playing animations

This functionality is deprecated. We strongly encourage playing and blending animations through a state machine.
In the previous version you were able to play an animation directly by passing animations: ['myAnimation'] to RiveAnimation. To achieve the same in the new version, use a SingleAnimationPainter and RiveArtboardWidget instead of RiveWidgetController and RiveWidget.
Single animation example
To play and mix multiple animations, you need to create your own painter. See the implementation of SingleAnimationPainter and extend it to create and advance multiple animations.

Handling State Machine inputs

Consider using Data Binding for more advanced use cases
StateMachineController has been removed and replaced with StateMachine. Important changes:
State Machine Inputs: New API
You can access the stateMachine from the RiveWidgetController:
It is recommended to manually dispose inputs when no longer needed: input.dispose()
Nested Inputs
You can access nested inputs by providing an optional path parameter:
Nested Inputs

Handling Rive Events

Consider using Data Binding instead of events for more advanced use cases.
RiveEvent has been removed and replaced with Event. Event is a sealed class with two options:
  • OpenUrlEvent
  • GeneralEvent
Registering an event listener:
Rive Events: New API
Accessing properties returns Map<String, CustomProperty>. CustomProperty is also a sealed class with options:
  • CustomNumberProperty
  • CustomBooleanProperty
  • CustomStringProperty
All of these have a value field. On the Event class, there are convenient accessors:

Layout changes

BoxFit → Fit
Previously we used Flutter’s BoxFit class. Now we use our own Fit which includes an extra option:

Asset loading changes

The FileAssetLoader class and all its subclasses have been removed:
  • CDNAssetLoader
  • LocalAssetLoader
  • CallbackAssetLoader
  • FallbackAssetLoader
Out-of-band asset loading
Asset types: FontAsset, ImageAsset, and AudioAsset.See this example that demonstrates loading random fonts.
Out-of-band assets: New API
You can also create the asset resource types manually and set them. This is useful if you want to preload the resources:
Key Changes:
  • assetLoader can no longer be an asynchronous lambda
  • ImageAsset.parseBytes(bytes)riveFactory.decodeImage(bytes) or asset.decode(bytes)
  • FontAsset.parseBytes(bytes)riveFactory.decodeFont(bytes) or asset.decode(bytes)
  • AudioAsset.parseBytes(bytes)riveFactory.decodeAudio(bytes) or asset.decode(bytes)
  • ImageAsset.image = valueImageAsset.renderImage(value) (returns boolean)
  • FontAsset.font = valueFontAsset.font(value) (returns boolean)
  • AudioAsset.audio = valueAudioAsset.audio(value) (returns boolean)

Text Run updates

We recommend using Data Binding instead to update text at runtime.
It’s no longer possible to access a TextValueRun object directly. Use these methods instead to access the String value:
Get/Set Text Run Value

Known missing features

These features are not available in v0.14.0 but may be added in future releases:
  • Automatic Rive CDN asset loading
  • speedMultiplier
  • useArtboardSize
  • clipRect
  • isTouchScrollEnabled
  • dynamicLibraryHelper

Removed code paths

All of the “runtime” Dart code has been removed from these paths:
  • src/controllers
  • src/core
  • src/generated
  • rive_core
  • utilities

Getting help

If you encounter issues during migration:
  1. Check the Rive Flutter documentation
  2. Review the Data Binding guide
  3. Visit the Rive community forums
  4. Report issues on the GitHub repository