letsar / local_hero

A widget which implicitly launches a hero animation when its position changed within the same route.
MIT License
208 stars 48 forks source link

Assertion failed in inn Animation Controller #5

Closed fly-qp closed 10 months ago

fly-qp commented 2 years ago

The animation works just fine but in the logs it looks very bad. Don't know what to do. Can I leave It like that.

The following assertion was thrown while notifying status listeners for AnimationController:
Assertion failed: file:///Users/apatrck03/Developer/flutter/packages/flutter/lib/src/rendering/object.dart:2221:12
!_debugDisposed
is not true

When the exception was thrown, this was the stack: 
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49  throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3    assertFailed
packages/flutter/src/rendering/object.dart 2221:13                            markNeedsPaint
packages/local_hero/src/rendering/local_hero_layer.dart 34:7                  [_onAnimationStatusChanged]
packages/flutter/src/animation/listener_helpers.dart 233:27                   notifyStatusListeners
packages/flutter/src/animation/animation_controller.dart 814:7                [_checkStatusChanged]
packages/flutter/src/animation/animation_controller.dart 367:5                set value
packages/local_hero/src/rendering/controller.dart 55:19                       [_onAnimationStatusChanged]
packages/flutter/src/animation/listener_helpers.dart 233:27                   notifyStatusListeners
packages/flutter/src/animation/animation_controller.dart 814:7                [_checkStatusChanged]
packages/flutter/src/animation/animation_controller.dart 830:5                [_tick]
packages/flutter/src/scheduler/ticker.dart 238:12                             [_tick]
packages/flutter/src/scheduler/binding.dart 1143:15                           [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1056:106                          <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:13      forEach
packages/flutter/src/scheduler/binding.dart 1054:16                           handleBeginFrame
packages/flutter/src/scheduler/binding.dart 975:5                             [_handleBeginFrame]
lib/_engine/engine/platform_dispatcher.dart 1018:13                           invoke1
lib/_engine/engine/platform_dispatcher.dart 136:5                             invokeOnBeginFrame
lib/_engine/engine.dart 431:45                                                <fn>
The AnimationController notifying status listeners was: AnimationController#2c63e(⏮ 0.000; paused)
Urvish24 commented 2 years ago

Did you find any solution for that?

bambuh commented 2 years ago

Same situation

pbouttier commented 2 years ago

Hi.

The solution : add if(!child.debugDisposed) in local_hero_layer.dart before markNeedsPaint();

void _onAnimationStatusChanged(AnimationStatus status) { 
    if (status == AnimationStatus.completed || 
        status == AnimationStatus.dismissed) { 
      if(!child.debugDisposed) markNeedsPaint(); 
    } 
  }
Urvish24 commented 2 years ago

@pbouttier

It getting build fail. can you describe with more information.

pbouttier commented 2 years ago

This solution works for me in flutter 2.5.3, with only this fix.

My usage : hero between two listview childrens.

Maybe in other cases, lattest stable this is different.

FrankDomburg commented 2 years ago

I am guessing that the animation completed, and the layer was removed. In that case, marking it for paint does not make sense. Haven't tested it (yet), but I think the whole line is redundant.

It seems to be linguistically. If the overlay is removed, when the animation is done, there is nothing to repaint. i've assumed that it is null when it was disposed. Flutter docs say, however, that it is null when assertions are disabled - so to me it seems not the best way to check for it, anyway.

Also, for null-safety the line is a little different

void _onAnimationStatusChanged(AnimationStatus status) { if (status == AnimationStatus.completed || status == AnimationStatus.dismissed) { if(!child.debugDisposed ?? true) markNeedsPaint(); } }

singularity-s0 commented 1 year ago

Hi.

The solution : add if(!child.debugDisposed) in local_hero_layer.dart before markNeedsPaint();

void _onAnimationStatusChanged(AnimationStatus status) { 
    if (status == AnimationStatus.completed || 
        status == AnimationStatus.dismissed) { 
      if(!child.debugDisposed) markNeedsPaint(); 
    } 
  }

Be careful, this might break the animation in release mode (debug mode works fine though)

juarezfranco commented 1 year ago

It's work, thanks

Snonky commented 1 year ago

Hi, I ran into the same issue. The solution with the debugDisposed check will not work in a release build because debug variables should not be used outside of assert statements.

Instead, a check for the attached property should solve the issue:

// in 'lib/src/rendering/local_hero_layer.dart'
void _onAnimationStatusChanged(AnimationStatus status) {
  if (!attached) {
    return;
  }
  if (status == AnimationStatus.completed ||
      status == AnimationStatus.dismissed) {
    markNeedsPaint();
  }
}