AvaloniaUI/Avalonia.Labs

lottie [ protected override Size MeasureOverride(Size availableSize)] error

ApaulMyLittleAirport opened this issue · 9 comments

I use the prism library, and I get this error when I switch to a different page and then back.

avalonia 11.0
windows10
.net7

<se:Lottie Canvas.Left="16" Canvas.Top="24" Height="32" Width="32" Path="avares://AGaxSat.Monitor/Resources/Logos/Wifi_Signal.json">
se:Lottie.RenderTransform

</se:Lottie.RenderTransform>
</se:Lottie>

image

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:

at SkiaSharp.SkottieApi.skottie_animation_get_size(IntPtr, SkiaSharp.SKSize*)

at SkiaSharp.Skottie.Animation.get_Size()
at Avalonia.Labs.Lottie.Lottie.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Canvas.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Canvas.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Grid.MeasureCell(Int32, Boolean)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean, Boolean ByRef)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean)
at Avalonia.Controls.Grid.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness)
at Avalonia.Controls.Border.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.StackPanel.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Presenters.ScrollContentPresenter.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Grid.MeasureCell(Int32, Boolean)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean, Boolean ByRef)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean)
at Avalonia.Controls.Grid.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness)
at Avalonia.Controls.Border.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness)
at Avalonia.Controls.Border.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.DockPanel.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Controls.Grid.MeasureCell(Int32, Boolean)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean, Boolean ByRef)
at Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean)
at Avalonia.Controls.Grid.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness)
at Avalonia.Controls.Presenters.ContentPresenter.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness)
at Avalonia.Controls.Presenters.ContentPresenter.MeasureOverride(Avalonia.Size)
at Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size)
at Avalonia.Layout.Layoutable.Measure(Avalonia.Size)
at Avalonia.Layout.LayoutManager.Measure(Avalonia.Layout.Layoutable)
at Avalonia.Layout.LayoutManager.ExecuteMeasurePass()
at Avalonia.Layout.LayoutManager.InnerLayoutPass()
at Avalonia.Layout.LayoutManager.ExecuteLayoutPass()
at Avalonia.Layout.LayoutManager.ExecuteQueuedLayoutPass()
at Avalonia.Media.MediaContext.FireInvokeOnRenderCallbacks()
at Avalonia.Media.MediaContext.RenderCore()
at Avalonia.Media.MediaContext.Render()
at Avalonia.Threading.DispatcherOperation.InvokeCore()
at Avalonia.Threading.DispatcherOperation.Execute()
at Avalonia.Threading.Dispatcher.ExecuteJob(Avalonia.Threading.DispatcherOperation)
at Avalonia.Threading.Dispatcher.ExecuteJobsCore()
at Avalonia.Threading.Dispatcher.Signaled()
at Avalonia.Win32.Win32Platform.WndProc(IntPtr, UInt32, IntPtr, IntPtr)
at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG ByRef)
at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG ByRef)
at Avalonia.Win32.Win32DispatcherImpl.RunLoop(System.Threading.CancellationToken)
at Avalonia.Threading.DispatcherFrame.Run(Avalonia.Threading.IControlledDispatcherImpl)
at Avalonia.Threading.Dispatcher.PushFrame(Avalonia.Threading.DispatcherFrame)
at Avalonia.Threading.Dispatcher.MainLoop(System.Threading.CancellationToken)
at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(System.String[])
at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(Avalonia.AppBuilder, System.String[], Avalonia.Controls.ShutdownMode)
at AGaxSat.Program.Main(System.String[])

I'm also having this issue when using a Frame from FluentAvalonia to navigate to a page with a Lottie control.

It looks like the OnUnloaded method (called after the control gets detached from the visual tree) is disposing the SkiaSharp animation. This sets the "_animation" variable inside the LottieCompositionCustomVisualHandler to null, but the "_animation" variable inside the Lottie doesn't get reset to null. So when the control is attached to the visual tree and MeasureOverride is called (this happens before OnLoaded is called), the null check for "_animation" has no effect and the Size property of the disposed animation is accessed, causing this error.

当使用FluentAvalonia的框架导航到带有Lottie控件的页面时,我也遇到了这个问题。

看起来 OnUnloaded 方法(在控件从可视化树分离后调用)正在释放 SkiaSharp 动画。这会将 LottieCompositionCustomVisualHandler 中的 “_animation” 变量设置为 null,但 Lottie 中的 “_animation” 变量不会重置为 null。因此,当控件附加到可视化树并调用 MeasureOverride 时(这发生在调用 OnLoaded 之前),对“_animation”的 null 检查不起作用,并且将访问已释放动画的 Size 属性,从而导致此错误。

It seems that this is not my problem, so do you have a solution?

It seems that this is not my problem, so do you have a solution?

I've created a fork with a fix that works for me: https://github.com/xLEGiON/Avalonia.Labs/commit/5da1518e7df15af828a6cf5bd94f65dcaef3d498

It is possible to use a local copy of this control with the fix above. That's what I'm currently doing.

I can create a pull request for the main repository if the author(s) are fine with the changes.

Edit: I should say that the fix I made probably isn't the optimal solution. It still loads the animation every time the control is loaded. This could hurt performance if the control is regularly loaded/unloaded. I think it might be better to only load the animation once, stop the animation once the control is unloaded, then start it again once loaded again (or load a new animation if the path changed).

看来这不是我的问题,那你有办法吗?

我创建了一个带有适合我的修复程序的分叉:xLEGiON@5da1518

可以将此控件的本地副本与上述修复一起使用。这就是我目前正在做的事情。

如果作者对更改感到满意,我可以为主存储库创建拉取请求。

编辑:我应该说我所做的修复可能不是最佳解决方案。每次加载控件时,它仍会加载动画。如果定期加载/卸载控件,这可能会损害性能。我认为最好只加载一次动画,在卸载控件后停止动画,然后在再次加载后再次启动它(或者在路径更改时加载新动画)。

I think you're doing the right thing, but maybe my programming level is limited and I can't help much, I'm sorry for that, thanks for the pointers, looking forward to the update!

I also got this problem. I have a user control used as a Page hosted in a ContentControl.
When I switch pages and back to the one with the Lottie it crashes in that method with the same error.
Looking forward to a official fix in this repo.

This commit should fix the problem 6d1deaa

If anybody wants to check if control works in your use case, building it from the master, it would help.

This fixes the exception but the animation won't load when the control is loaded again because the "_preloadPath" variable has been set to null by OnLoaded. My fix above has a few changes with this that I didn't mention here. After that fix, it seems "_preloadPath" actually serves no purpose and could be replaced by reading the Path property.

@maxkatz6 your commit 6d1deaa did not fix the problem in my case.

With your commit it wont crash with memory access exception, but the animation is not loaded after the page is navigated back. Runs first time, you navigate away, comes back, animation is gone. Same symptom as before, just instead of crashing, animation wont load. @xLEGiON fix seems to work fine for me. I am using his fork for now.

@xLEGiON can you create a PR with your changes? Thanks.