-
Notifications
You must be signed in to change notification settings - Fork 226
Description
Description
When using Rive Flutter runtime 0.14.0-dev.14 with a .riv file that contains an image asset, the assetLoader callback passed to File.asset is only invoked when the image’s export options in the Rive Editor are set to:
Type: Embedded+Behavior: Automatic, orType: Embedded+Behavior: Force Export
For any other combination (in particular when using Type: Referenced), the assetLoader callback is never called for that image asset.
My understanding from the docs is that assetLoader should be invoked for every asset the runtime detects in the .riv file, regardless of whether the asset is embedded or referenced, so that the app can provide bytes when needed (e.g. for referenced assets, where bytes would be null/empty and the app can supply them).
Right now that does not seem to be the case in 0.14.0-dev.14, and it appears tied to the export options used in the Rive Editor.
Steps To Reproduce
- In Rive Editor:
- Create a new file with a single artboard and a simple animation.
- Import an image asset (e.g.
example_image.webporexample_image.png). - Place the image on the artboard so that it is clearly in use in the animation.
- In the image’s Export Options:
- Set Type: Embedded, Behavior: Automatic.
- Export the file via Export for Runtimes and place the resulting
.rivin a Flutter project (e.g.assets/rive/example.riv).
- In Flutter (rive: 0.14.0-dev.14)
- Add the
.rivtopubspec.yamlunderassets: - Use a minimal widget that loads the file with
File.assetand anassetLoaderthat logs every asset:
class RiveAssetLoaderDemo extends StatefulWidget {
const RiveAssetLoaderDemo({super.key});
@override
State<RiveAssetLoaderDemo> createState() => _RiveAssetLoaderDemoState();
}
class _RiveAssetLoaderDemoState extends State<RiveAssetLoaderDemo> {
FileLoader? _fileLoader;
bool _initializing = true;
@override
void initState() {
super.initState();
_loadFile();
}
Future<void> _loadFile() async {
final file = await File.asset(
'path/to/animation/',
riveFactory: Factory.rive,
assetLoader: (FileAsset asset, Uint8List? bytes) {
final msg = 'assetLoader: name=${asset.name}, ext=${asset.fileExtension}';
debugPrint(msg);
return false;
},
);
if (!mounted || file == null) {
setState(() => _initializing = false);
return;
}
setState(() {
_fileLoader = FileLoader.fromFile(
file,
riveFactory: Factory.rive,
);
_initializing = false;
});
}
@override
void dispose() {
_fileLoader?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_initializing || _fileLoader == null) {
return const Center(child: CircularProgressIndicator());
}
return Column(
children: [
Expanded(
child: RiveWidgetBuilder(
fileLoader: _fileLoader!,
artboardSelector: ArtboardSelector.byIndex(0),
stateMachineSelector: StateMachineSelector.byDefault(),
dataBind: DataBind.auto(),
builder: (context, state) => switch (state) {
RiveLoading() => const Center(
child: CircularProgressIndicator(),
),
RiveFailed() => Center(
child: Text('Failed: ${state.error}'),
),
RiveLoaded() => RiveWidget(
controller: state.controller,
fit: Fit.contain,
),
},
),
),
],
);
}
}
- Run the app and check the console.
Observe that only these two combinations of export options does a console log:
Type: Embedded + Behavior: Automatic
Embedded + Behavior: Force Export
Now re-test with other combinaitons of export options:
- Type: Referenced + Behavior: Include in Export / Automatic
- Type: Referenced + Behavior: Force Export
- Type: Embedded + Behavior: Prevent Export
- Type: Referenced + Behavior: Prevent Export
For all combinations other than Embedded + Automatic and Embedded + Force Export, assetLoader is never invoked for the image asset (no log lines for that asset).
This is true even in cases where my expectation is that the asset should still exist in the file as a referenced asset and therefore be visible to the runtime (e.g. Type: Referenced + non-“Prevent Export” behavior).
Source .riv/.rev file
I have attached the runtime-exported .riv files that reproduce the issue. I'll also add the corresponding .rev backup file from the Editor.
Expected behavior
My understanding from the 0.14 runtime docs is that the assetLoader callback passed to File.asset should be called for every asset the runtime detects from the .riv file on load, regardless of how the asset’s Type is configured (Embedded vs Referenced), and regardless of the Behavior as long as the asset is actually present in the exported file.
Screenshots
Not applicable
Device & Versions (please complete the following information)
- Device: Android Pixel 10 Pro (physical device)
- OS: Android SDK API Level 36 (Android 16)
- Flutter Version:
Flutter 3.38.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 19074d12f7 (2 weeks ago) • 2025-11-20 17:53:13 -0500
Engine • hash 8bf2090718fea3655f466049a757f823898f0ad1 (revision 13e658725d) (13 days ago) • 2025-11-20 20:19:23.000Z
Tools • Dart 3.10.1 • DevTools 2.51.1
Additional context
- The same .riv files display correctly in the Rive Editor.
- From the app side, the wiring appears correct because
assetLoaderdoes fire for embedded assets; it’s specifically other export option combinations that cause it not to be invoked. - My goal is to use Referenced image assets and provide the image bytes at runtime from Flutter (via
AssetBundle), but this currently seems impossible because the runtime never callsassetLoaderfor those assets in0.14.0-dev.14. - If there is a misunderstanding of how the new 0.14 runtime is intended to behave with respect to
assetLoaderand export options, clarification in the docs would also be very helpful.
Cheers!