Version 0.15.0
Two things need migration work in this release:- Data Binding binds when you create a
RiveWidgetController, and the separatedataBindcall 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 is3.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:
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
- New API
- Old API
Legacy bridge
To keep existing call sites compiling while you migrate: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 asrive 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:
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 twoRiveWidgets 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:- Rive Renderer
- Data Binding
- Layouts
- Scrolling
- N-Slicing
- Vector Feathering
- All other features added to Rive that did not make it to the previous versions of Rive Flutter
- Includes the latest fixes and improvements for the Rive C++ runtime
- Adds prebuilt libraries, with the ability to build manually. See the rive_native package for more information
- Removes the
rive_commonpackage and replaces it withrive_native
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 callRiveNative.init at the start of your app, or before you use Rive. For example, in main.dart:
Migration guide
Quick migration checklist
- ✅ Update your
pubspec.yamldependencies to use version0.14.0or later - ✅ Add
RiveNative.init()to yourmain()function, or call before using Rive. - ✅ Replace
RiveandRiveAnimationwidgets withRiveWidgetorRiveWidgetBuilder - ✅ Update your controllers to use the new API, see
RiveWidgetController - ✅ Review and update any custom asset loading code
- ✅ Test your graphics and interactions
Removed classes
The following classes have been completely removed:RiveandRiveAnimationwidgets → UseRiveWidgetandRiveWidgetBuilderRiveAnimationControllerand its subclasses → UseRiveWidgetController,SingleAnimationPainter, andStateMachinePainterOneShotAnimationandSimpleAnimation→ UseSingleAnimationPainterto play individual animationsStateMachineController→ UseStateMachineinstead (can be accessed viaRiveWidgetController.stateMachine)RiveEvent→ Replaced withEventSMITrigger→ Replaced withTriggerInputSMIBool→ Replaced withBooleanInputSMINumber→ Replaced withNumberInputFileAssetLoader→ Replaced with optional callback when creating aFile
Loading Rive files
RiveFile has been removed and replaced with File. Important changes:
- New API
- Old API
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).
Key Changes:
- Creating a Rive File now requires a factory (
Factory.riveorFactory.flutter) - Replace
RiveFile.importwithFile.decode()which returns aFuture<File> - Replace
mainArtboardwithdefaultArtboard() - Replace
artboardByName(name)withartboard(name) - Replace
RiveFile.networkwithFile.url - Replace
RiveFile.filewithFile.path
Widget migration
See the updated example app for a complete migration guide, including how to use the newRiveWidget and RiveWidgetBuilder APIs.
- New API - Option 1
- New API - Option 2
- Old API
Using RiveWidgetBuilder
Controller migration
Example using the new
RiveWidgetController:
Using RiveWidgetController
Specifying Artboard and State Machine
Playing animations
In the previous version you were able to play an animation directly by passinganimations: ['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
StateMachineController has been removed and replaced with StateMachine. Important changes:
- New API
- Old API
State Machine Inputs: New API
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 optionalpath parameter:
Nested Inputs
Handling Rive Events
RiveEvent has been removed and replaced with Event. Event is a sealed class with two options:
OpenUrlEventGeneralEvent
- New API
- Old API
Rive Events: New API
properties returns Map<String, CustomProperty>. CustomProperty is also a sealed class with options:
CustomNumberPropertyCustomBooleanPropertyCustomStringProperty
value field. On the Event class, there are convenient accessors:
Layout changes
BoxFit → Fit
Previously we used Flutter’sBoxFit class. Now we use our own Fit which includes an extra option:
Asset loading changes
TheFileAssetLoader class and all its subclasses have been removed:
CDNAssetLoaderLocalAssetLoaderCallbackAssetLoaderFallbackAssetLoader
Out-of-band asset loading
- New API
- Old API
Asset types: You can also create the asset resource types manually and set them. This is useful if you want to preload the resources:
FontAsset, ImageAsset, and AudioAsset.See this example that demonstrates loading random fonts.Out-of-band assets: New API
assetLoadercan no longer be an asynchronous lambdaImageAsset.parseBytes(bytes)→riveFactory.decodeImage(bytes)orasset.decode(bytes)FontAsset.parseBytes(bytes)→riveFactory.decodeFont(bytes)orasset.decode(bytes)AudioAsset.parseBytes(bytes)→riveFactory.decodeAudio(bytes)orasset.decode(bytes)ImageAsset.image = value→ImageAsset.renderImage(value)(returns boolean)FontAsset.font = value→FontAsset.font(value)(returns boolean)AudioAsset.audio = value→AudioAsset.audio(value)(returns boolean)
Text Run updates
It’s no longer possible to access aTextValueRun object directly. Use these methods instead to access the String value:
Get/Set Text Run Value
Known missing features
These features are not available inv0.14.0 but may be added in future releases:
- Automatic Rive CDN asset loading
speedMultiplieruseArtboardSizeclipRectisTouchScrollEnableddynamicLibraryHelper
Removed code paths
All of the “runtime” Dart code has been removed from these paths:src/controllerssrc/coresrc/generatedrive_coreutilities
Getting help
If you encounter issues during migration:- Check the Rive Flutter documentation
- Review the Data Binding guide
- Visit the Rive community forums
- Report issues on the GitHub repository