xvrh / lottie-flutter

Render After Effects animations natively on Flutter. This package is a pure Dart implementation of a Lottie player.
https://pub.dev/packages/lottie
MIT License
1.16k stars 196 forks source link

BUG: Lottie.asset() in showDialog causes Failed assertion: dirty: is not true #258

Closed juskek closed 1 year ago

juskek commented 1 year ago

Steps to Reproduce

  1. Checkout the following commit
  2. Execute flutter run
  3. Press 'Show Dialog' button to show working animation
  4. Dismiss dialog by pressing outside barrier
  5. Press 'Show Dialog' button again to show error

Expected results: Upon invoking showDialog, I was expecting to see the same animation widget again.

Actual results: Error screen with log:

The following assertion was thrown building DefaultTextStyle(debugLabel: (englishLike bodyMedium
2014).merge(blackCupertino bodyMedium), inherit: false, color: Color(0xdd000000), family: .SF UI
Text, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap:
wrapping at box width, overflow: clip):
'package:flutter/src/widgets/framework.dart': Failed assertion: line 4610 pos 12: '!_dirty': is not
true.
Code sample ```dart class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( child: const Text('Show Dialog'), onPressed: () => showDialog( barrierDismissible: true, context: context, builder: (context) => const Dialog( child: SizedBox( height: 300, width: 300, child: LottieAnimationWidget( assetPath: 'assets/animations/loading_success.json'), ), ), )), ), ); } } ``` ```dart class LottieAnimationWidget extends StatefulWidget { const LottieAnimationWidget({required this.assetPath, super.key}); final String assetPath; @override State createState() => _LottieAnimationWidgetState(); } class _LottieAnimationWidgetState extends State with TickerProviderStateMixin { late final AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController(vsync: this); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Lottie.asset( widget.assetPath, controller: _controller, onLoaded: (composition) { setState(() { _controller.duration = composition.duration; _controller.forward(); }); }, ); } } ```
Logs ``` flutter run --verbose ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following assertion was thrown building DefaultTextStyle(debugLabel: (englishLike bodyMedium 2014).merge(blackCupertino bodyMedium), inherit: false, color: Color(0xdd000000), family: .SF UI Text, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip): 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4610 pos 12: '!_dirty': is not true. Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause. In either case, please report this assertion by filing a bug on GitHub: https://github.com/flutter/flutter/issues/new?template=2_bug.md The relevant error-causing widget was: Dialog Dialog:file:///Users/justinkek/Desktop/Repositories/_temp/flutter_bugs/lib/home_page.dart:16:47 When the exception was thrown, this was the stack: #2 Element.rebuild (package:flutter/src/widgets/framework.dart:4610:12) #3 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4859:5) #4 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5041:11) #5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4853:5) ... Normal element mounting (279 frames) #284 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3863:16) #285 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6435:36) #286 Element.updateChild (package:flutter/src/widgets/framework.dart:3592:18) #287 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5964:32) #288 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6460:17) #289 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #290 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #291 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11) #292 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #293 StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5) #294 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #295 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #296 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #297 ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5) #298 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #299 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #300 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #301 ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5) #302 _InheritedNotifierElement.update (package:flutter/src/widgets/inherited_notifier.dart:107:11) #303 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #304 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14) #305 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #306 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #307 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11) #308 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #309 StatefulElement.update (package:flutter/src/widgets/framework.dart:5082:5) #310 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #311 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14) #312 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #313 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6307:14) #314 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #315 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #316 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #317 ProxyElement.update (package:flutter/src/widgets/framework.dart:5228:5) #318 Element.updateChild (package:flutter/src/widgets/framework.dart:3570:15) #319 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4904:16) #320 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5050:11) #321 Element.rebuild (package:flutter/src/widgets/framework.dart:4604:5) #322 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2667:19) #323 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21) #324 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5) #325 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15) #326 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9) #327 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5) #328 _invoke (dart:ui/hooks.dart:148:13) #329 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5) #330 _drawFrame (dart:ui/hooks.dart:115:31) (elided 2 frames from class _AssertionError) ════════════════════════════════════════════════════════════════════════════════════════════════════ ``` ``` flutter analyze Analyzing flutter_bugs... No issues found! (ran in 3.4s) ``` ``` flutter doctor -v [✓] Flutter (Channel stable, 3.3.10, on macOS 13.1 22C65 darwin-x64, locale en-SG) • Flutter version 3.3.10 on channel stable at /Users/justinkek/Desktop/Repositories/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 135454af32 (5 weeks ago), 2022-12-15 07:36:55 -0800 • Engine revision 3316dd8728 • Dart version 2.18.6 • DevTools version 2.15.0 [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/justinkek/Library/Android/sdk • Platform android-33, build-tools 32.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14B47b • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) [✓] VS Code (version 1.74.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.56.0 [✓] Connected device (3 available) [✓] HTTP Host Availability • All required HTTP hosts are available • No issues found! ```
xvrh commented 1 year ago

I think the quickest fix for you is to just remove the setState in the onLoaded callback. It shouldn't be needed.

      onLoaded: (composition) {
        _controller.duration = composition.duration;
        _controller.forward();
      },

But still this is probably a regression with v2.1.0 and the synchronous callback. I'll have a look at that.

juskek commented 1 year ago

Hey @xvrh, thanks for the quick reply.

Removing setState worked! I might have misunderstood the necessity of setState in the onLoaded callback in the following example. Is there any case where I should include setState there then?