Lottie vs Rive in Flutter: Picking an Animation Runtime for Your App
A practical comparison of the lottie and rive Flutter packages: rendering models, APIs, performance trade-offs, and how to choose between After Effects JSON and Rive's interactive state machines.
Published on • October 3, 2026
AI Assistant

Flutter’s built-in animation primitives cover tweens, springs and heroes beautifully — but the moment a designer hands you an After Effects export or an interactive character, you need a runtime that plays authoring-tool files. The two packages that show up in almost every shortlist are lottie and rive.
Sources: lottie on pub.dev, rive on pub.dev.
The two models, in one paragraph each
Lottie renders animations exported from Adobe After Effects with the Bodymovin plugin. The package is a pure Dart port of Lottie-android — it parses the JSON (or .zip/.lottie/Telegram .tgs archives) and draws frames itself, so the same file works on Android, iOS, macOS, Linux, Windows and Web with no native library. The file is the animation: what the motion designer exported is what ships.
Rive is an end-to-end pipeline: a browser-based editor, a stateful .riv graphics format, and a runtime with its own vector renderer. Since Rive 0.14 the Flutter package leans on rive_native, a native library downloaded during build, and lets you choose either the Rive renderer or Flutter’s own renderer (Skia/Impeller) per File.
API feel: one widget vs. a scene graph
Lottie is deliberately tiny:
Lottie.asset('assets/success.json');
Lottie.network(
'https://assets.example.com/loading.json',
width: 200, height: 200, fit: BoxFit.fill,
);
Need playback control? Hand it an AnimationController and you get the full Flutter animation toolkit for free — pause, reverse, seek, drive it from a gesture:
Lottie.asset(
'assets/success.json',
controller: _controller,
onLoaded: (composition) {
_controller
..duration = composition.duration
..forward();
},
);
You can also load compositions yourself with AssetLottie(...).load() and draw individual frames with LottieDrawable on a CustomPainter, and override layer properties at runtime through ValueDelegate (text, colour, opacity, position).
Rive’s API is closer to a scene graph: you load a File, pick an artboard, and drive a state machine — Rive’s own interactive graph of states, inputs and transitions — plus data binding. That is the fundamental difference: Lottie plays a timeline, Rive plays a machine.
Feature comparison
lottie 3.6.x | rive 0.14.x | |
|---|---|---|
| Authoring tool | Adobe After Effects + Bodymovin | Rive editor (rive.app) |
| File format | JSON (.json, .zip, .tgs, .lottie) | .riv |
| Implementation | Pure Dart | Dart API + rive_native |
| Interactivity | Timeline control, ValueDelegate overrides | State machines, data binding, widgets |
| Renderers | Flutter’s renderer | Rive renderer or Flutter renderer |
| Platforms | Android, iOS, Linux, macOS, Windows, Web | Android, iOS, Linux, macOS, Windows, Web |
| Size / traction | 4.5k likes, 2.06M downloads | 1.9k likes, 461k downloads |
| License | MIT | MIT |
Performance notes worth knowing
- Lottie’s
renderCache(added in v3.0) renders frames lazily into an offscreen cache so subsequent runs are cheaper. It trades memory for CPU/GPU cost — worth enabling for long-running looping animations such as loaders. - Frame rate: Lottie plays at the After Effects export rate (often 10 or 30 FPS) by default, which is power-friendly on a 120 Hz phone. Override with
frameRate: FrameRate.maxwhen you need buttery motion. - Rive renderer choice:
File.asset('assets/x.riv', riveFactory: Factory.rive)picks the Rive renderer;Factory.flutteruses Flutter’s. If you see a visual discrepancy on iOS, the Rive docs suggest first re-running withflutter run --no-enable-impellerto check whether it’s an Impeller-specific issue. - Native libraries: Rive downloads prebuilt
rive_nativebinaries duringflutter run/flutter build; a manual fallback exists (dart run rive_native:setup --verbose --clean --platform macos). On CI, runflutter clean && flutter pub getfirst if the libraries look stale.
Choosing between them
Reach for Lottie when:
- Your designers already live in After Effects and hand over
.jsonexports (LottieFiles workflows). - The animation is decorative: loaders, success checks, empty states, stickers.
- You want zero native dependencies and maximum platform reach, including Web with no extra build steps.
Reach for Rive when:
- The animation must react: menus, toggles, characters that respond to touch or app state.
- You want state machines instead of hand-wiring playback in Dart.
- Asset size matters — Rive’s binary format plus state-machine logic usually beats a long JSON timeline.
- You’re building a game or a highly branded UI and want consistent rendering via Rive’s own renderer.
Many teams end up using both: Lottie for one-off motion assets, Rive for the interactive centerpiece.
Getting started
dependencies:
lottie: ^3.6.1
rive: ^0.14.11
Lottie’s example folder (via dart pub unpack lottie) contains samples for controllers, delegates and custom drawing; Rive’s getting-started guide lives at rive.app/docs/runtimes/flutter/flutter. Both packages are MIT-licensed and published by verified publishers (xaha.dev and rive.app).
Whichever you pick, keep animations out of the build path: load them lazily, respect prefers-reduced-motion, and test on a low-end device — motion that looks free on a flagship often isn’t.