Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Carousel issue - Canvas: trying to use a recycled bitmap android.graphics.Bitmap #10032

Closed
mehrdadab opened this issue Sep 10, 2022 · 32 comments · Fixed by #12310
Closed

Carousel issue - Canvas: trying to use a recycled bitmap android.graphics.Bitmap #10032

mehrdadab opened this issue Sep 10, 2022 · 32 comments · Fixed by #12310
Assignees
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView fixed-in-7.0.59 Look for this fix in 7.0.59! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.1.7762 Look for this fix in 8.0.0-preview.1.7762! high It doesn't work at all, crashes or has a big impact. p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 t/bug Something isn't working

Comments

@mehrdadab
Copy link

Description

I am using CarouselView in .Net Maui, I have four image Urls that I assign to an Image component inside a CarouselView, my code is as below:

       <CarouselView ItemsSource="{Binding CatList}" IndicatorView="indicatorView" CurrentItemChangedCommand="{Binding CarouselImageChanged}" >
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <VerticalStackLayout MinimumHeightRequest="250" MaximumHeightRequest="300" Margin="0,0,0,5" Padding="1">
                        <Image Source="{Binding ImageUrl}"  />
                    </VerticalStackLayout>

                </DataTemplate>
            </CarouselView.ItemTemplate>

        </CarouselView>
        <IndicatorView x:Name="indicatorView"
                   IndicatorColor="LightGray"
                   SelectedIndicatorColor="DarkGray"
                   HorizontalOptions="Center" />

In the first round, when I slide through images, it works perfectly but crashes in the second round after the first or second image.
When I debug, it shows the exception below:
Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@bb33eb5'

My images are large and if I resize them the issue may be resolved, but I believe it should be a way to disable recycling images, in case there is no way to resize them.

Steps to Reproduce

  1. Create a .net Maui app
  2. Create a Page with CarouselView and an Image Component inside it.
  3. Bind a list that contains image URLs(to be assigned to the Image source) to CarouselView(The images must be large)
  4. Run the application on an android device and swipe the images,
  5. On the second round it crashes and the exception is Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@bb33eb5'

Link to public reproduction project repository

N/A

Version with bug

6.0.400

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android Version 9 - API 28, Emulator Android 11.0 API 30

Did you find any workaround?

I noticed if I add CurrentItemChangedCommand to the CarouselView it will happen later on Emulator(Sometimes at the third round)

Relevant log output

No response

@mehrdadab mehrdadab added the t/bug Something isn't working label Sep 10, 2022
@mehrdadab
Copy link
Author

I found out this issue happens only in Debug mode. It works fine in Release mode.

@jsuarezruiz jsuarezruiz added high It doesn't work at all, crashes or has a big impact. area-controls-collectionview CollectionView, CarouselView, IndicatorView labels Sep 12, 2022
@PureWeen PureWeen added this to the Backlog milestone Sep 14, 2022
@PureWeen
Copy link
Member

@mattleibow @rmarinho any additional thoughts?

@mattleibow
Copy link
Member

I wonder if we just need to stop explicitly disposing images and let glide do it for us. In the image source service, we probably need to dispose when we are returning bitmap/drawable, but do nothing when loading into an image view.

@jsuarezruiz
Copy link
Contributor

Could you attach a small sample where reproduce the issue?

@nk54
Copy link

nk54 commented Oct 7, 2022

Same issue on Android (it works in Windows the first time only : if I go from last image to first image again, nothing happens anymore). I try to switch the background image of a page. Each second, I change the image.

Here is some basic code to reproduce the bug : on MainPage.xaml.cs
private readonly string[] _images = new string[3];
private int _index = 0;
private string _splashSource;
public string SplashSource
{
get => _splashSource;
set => Set(ref _splashSource, value); // you can set _splashSource and raise INPC here to replace Set
}
public async Task CarouselAsync(int index)
{
await Task.Delay(1000);
_index = index == _images.Length ? 0 : index;
SplashSource = _images[index];
await CarouselAsync(_index + 1);
}

And in MainPage.xaml :
<Image Aspect="AspectFill" Source="{Binding SplashSource}" />

@espenrl
Copy link
Contributor

espenrl commented Nov 16, 2022

I get the same using a CarouselView with an Image in the ItemTemplate. Android 13 with .NET 7 GA tooling.

Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@83fdbc8'

Here is a repro. Just scroll and scroll until it eventually happens. Usually not very long.

https://github.com/espenrl/issue-repro/tree/main/CarouselView-android-recycled-bitmap

@asabbah1
Copy link

Same Issue here in CollectionView
Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@44625eb'

@AmSmart
Copy link

AmSmart commented Nov 18, 2022

Yep, just experienced the same issue with the CollectionView on Android. Any workarounds for now?

@terraslate
Copy link

I found out this issue happens only in Debug mode. It works fine in Release mode.

For me it occurs in release mode.

@terraslate
Copy link

terraslate commented Nov 21, 2022

I wonder if we just need to stop explicitly disposing images and let glide do it for us. In the image source service, we probably need to dispose when we are returning bitmap/drawable, but do nothing when loading into an image view.

https://developer.android.com/topic/performance/graphics/manage-memory

perhaps this helps

and this

#11519

Unfortunately this bug is so unpredictable in the current implementation we cannot release anything on maui to the public. it could blow up on any device at any time as we've seen on our test devices. Regards

@FM1973
Copy link

FM1973 commented Nov 22, 2022

same here. we are about to release the app to public, but we can´t. The error randomly happens. This is really a show stopper!

@FM1973
Copy link

FM1973 commented Nov 22, 2022

This happens for CarouselView and CollectionView.
We got our app ready and it´s pretty stable except this bug (99% of crash reports).
Can someone tell me if there is a workaround? A custom image control for example?
Our customer is getting nervous and so do I.

I forgot: in my case this happens primarily in release mode.

@FM1973
Copy link

FM1973 commented Nov 22, 2022

Example error:

Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualBooleanMethod(JniObjectReference , JniObjectReference , JniMethodInfo , JniArgumentValue* )
Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualBooleanMethod(String , IJavaPeerable , JniArgumentValue* )
Android.Views.ViewGroup.DrawChild(Canvas , View , Int64 )
Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.DrawChild(Canvas canvas, View child, Int64 drawingTime)
Android.Views.ViewGroup.n_DrawChild_Landroid_graphics_Canvas_Landroid_view_View_J(IntPtr , IntPtr , IntPtr , IntPtr , Int64 )
Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLJ_Z(_JniMarshal_PPLLJ_Z , IntPtr , IntPtr , IntPtr , IntPtr , Int64 )
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@ea3dcdb
android.graphics.BaseCanvas.throwIfCannotDraw BaseCanvas.java:87
android.graphics.RecordingCanvas.throwIfCannotDraw RecordingCanvas.java:264
android.graphics.BaseRecordingCanvas.drawBitmap BaseRecordingCanvas.java:97
android.graphics.drawable.BitmapDrawable.draw BitmapDrawable.java:560
android.widget.ImageView.onDraw ImageView.java:1462
android.view.View.draw View.java:23898
android.view.View.updateDisplayListIfDirty View.java:22767
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5138
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
androidx.drawerlayout.widget.DrawerLayout.drawChild DrawerLayout.java:1478
crc640ec207abc449b2ca.ShellFlyoutRenderer.n_drawChild(Native Method)
crc640ec207abc449b2ca.ShellFlyoutRenderer.drawChild ShellFlyoutRenderer.java:57
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.draw View.java:23901
com.android.internal.policy.DecorView.draw DecorView.java:1378
android.view.View.updateDisplayListIfDirty View.java:22767
android.view.ThreadedRenderer.updateViewTreeDisplayList ThreadedRenderer.java:602
android.view.ThreadedRenderer.updateRootDisplayList ThreadedRenderer.java:608
android.view.ThreadedRenderer.draw ThreadedRenderer.java:684
android.view.ViewRootImpl.draw ViewRootImpl.java:5440
android.view.ViewRootImpl.performDraw ViewRootImpl.java:5148
android.view.ViewRootImpl.performTraversals ViewRootImpl.java:4212
android.view.ViewRootImpl.doTraversal ViewRootImpl.java:2919
android.view.ViewRootImpl$TraversalRunnable.run ViewRootImpl.java:10491
android.view.Choreographer$CallbackRecord.run Choreographer.java:1108
android.view.Choreographer.doCallbacks Choreographer.java:866
android.view.Choreographer.doFrame Choreographer.java:797
android.view.Choreographer$FrameDisplayEventReceiver.run Choreographer.java:1092
android.os.Handler.handleCallback Handler.java:938
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loopOnce Looper.java:226
android.os.Looper.loop Looper.java:313
android.app.ActivityThread.main ActivityThread.java:8669
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:571
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1135

@FM1973
Copy link

FM1973 commented Nov 22, 2022

another one:

Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod(JniObjectReference , JniObjectReference , JniMethodInfo , JniArgumentValue* )
Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String , IJavaPeerable , JniArgumentValue* )
Android.Views.View.DispatchDraw(Canvas )
Microsoft.Maui.Platform.ContentViewGroup.DispatchDraw(Canvas canvas)
Android.Views.View.n_DispatchDraw_Landroid_graphics_Canvas_(IntPtr , IntPtr , IntPtr )
Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V , IntPtr , IntPtr , IntPtr )
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@de9dae6
android.graphics.BaseCanvas.throwIfCannotDraw BaseCanvas.java:87
android.graphics.RecordingCanvas.throwIfCannotDraw RecordingCanvas.java:264
android.graphics.BaseRecordingCanvas.drawBitmap BaseRecordingCanvas.java:97
android.graphics.drawable.BitmapDrawable.draw BitmapDrawable.java:560
android.widget.ImageView.onDraw ImageView.java:1444
android.view.View.draw View.java:23898
android.view.View.updateDisplayListIfDirty View.java:22767
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
crc6452ffdc5b34af3a0f.ContentViewGroup.n_dispatchDraw(Native Method)
crc6452ffdc5b34af3a0f.ContentViewGroup.dispatchDraw ContentViewGroup.java:59
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.draw View.java:23901
androidx.core.widget.NestedScrollView.draw NestedScrollView.java:2209
android.view.View.updateDisplayListIfDirty View.java:22767
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.updateDisplayListIfDirty View.java:22753
android.view.View.draw View.java:23628
android.view.ViewGroup.drawChild ViewGroup.java:5355
androidx.recyclerview.widget.RecyclerView.drawChild RecyclerView.java:5204
android.view.ViewGroup.dispatchDraw ViewGroup.java:5112
android.view.View.draw View.java:23901
androidx.recyclerview.widget.RecyclerView.draw RecyclerView.java:4603
android.view.View.updateDisplayListIfDirty View.java:22767
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:5339
android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:5311
android.view.View.updateDisplayListIfDirty View.java:22714
android.view.ThreadedRenderer.updateViewTreeDisplayList ThreadedRenderer.java:602
android.view.ThreadedRenderer.updateRootDisplayList ThreadedRenderer.java:608
android.view.ThreadedRenderer.draw ThreadedRenderer.java:684
android.view.ViewRootImpl.draw ViewRootImpl.java:5445
android.view.ViewRootImpl.performDraw ViewRootImpl.java:5153
android.view.ViewRootImpl.performTraversals ViewRootImpl.java:4217
android.view.ViewRootImpl.doTraversal ViewRootImpl.java:2924
android.view.ViewRootImpl$TraversalRunnable.run ViewRootImpl.java:10513
android.view.Choreographer$CallbackRecord.run Choreographer.java:1108
android.view.Choreographer.doCallbacks Choreographer.java:866
android.view.Choreographer.doFrame Choreographer.java:797
android.view.Choreographer$FrameDisplayEventReceiver.run Choreographer.java:1092
android.os.Handler.handleCallback Handler.java:938
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loopOnce Looper.java:226
android.os.Looper.loop Looper.java:313
android.app.ActivityThread.main ActivityThread.java:8751
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:571
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1135

@FM1973
Copy link

FM1973 commented Nov 22, 2022

Hope this helps to nail down the problem

@angelru
Copy link

angelru commented Nov 25, 2022

The same issue...

@terraslate
Copy link

Hope the team get the importance of this. It's a fundamental building block of all these views that images are handled correctly as a base requirement, there cannot be any room for error otherwise your app will just crash and along with it your brand image. Without this it is not possible to release any Maui app at this time unfortunately. Luckily mine was a port from Xamarin, so I've reworked the changes back into the old app that the Maui port was going to replace and will revisit in another 3 to 6 months time to see if things have improved. Incidentally the performance of the scrolling in the Maui app also would not have let us release either, but that is a different topic.

@1357310795
Copy link

Not only CarouselView, but the Microsoft.Maui.Controls.Image control will produce this error on switching ImageSource😓

image

@FM1973
Copy link

FM1973 commented Nov 26, 2022

@1357310795
Yes, I can confirm that.

@AmSmart
Copy link

AmSmart commented Nov 28, 2022

@jsuarezruiz @mattleibow

This might need retagging. It looks as though it is unrelated to the CollectionView or CarouselView but happens in the Image control when the source is being switched.

This obviously will impact any Android Control that uses the RecyclerView under the hood (I believe this includes both CollectionView and CarouselView), since that will likely attempt to reuse the same Image Control while switching the sources as a user scrolls.

@angelru
Copy link

angelru commented Nov 28, 2022

I don't know if it has something to do with it, but with CollectionView with images, when you scroll quickly it seems that the source of the images is exchanged.

@angelru
Copy link

angelru commented Nov 30, 2022

any solution to 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@5601f7b' ?

@mohachouch
Copy link
Contributor

mohachouch commented Nov 30, 2022

@jsuarezruiz @mattleibow @PureWeen @hartez @davidortinau @maddymontaquila

This bug has been declared multiple times and the first time in June 2022.

https://github.com/dotnet/maui/issues?q=is%3Aissue+is%3Aopen+Canvas%3A+trying+to+use+a+recycled+bitmap

When do you plan to fix it. The bug is rated high but no one is taking care of it. How do you expect us to trust Maui if the same Xamarin Forms slow fix issues happen again. As part of my company we are seriously considering moving to another technology (native or flutter). We're tired of always having to find workarounds !

@mohachouch
Copy link
Contributor

mohachouch commented Dec 1, 2022

I spent a few hours to analyze this problem.

This bug was created following this pull request: #7348

While waiting for Microsoft to permanently fix this bug, the workaround consists of redoing the clear before each source image change.

Below is an example of code to add the clear in the source image mapping.

This workaround is applicable to the following bug
#11519 #11130 #10032 #9712 #8809 #9011
#8178 #8809

using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;

namespace MauiCanvas;

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});

#if __ANDROID__
        ImageHandler.Mapper.PrependToMapping(nameof(Microsoft.Maui.IImage.Source), (handler, view) => PrependToMappingImageSource(handler, view));
#endif

        return builder.Build();
	}

#if __ANDROID__
    public static void PrependToMappingImageSource(IImageHandler handler, Microsoft.Maui.IImage image)
    {
        handler.PlatformView?.Clear();
    }
#endif

}

@FM1973
Copy link

FM1973 commented Dec 1, 2022

@mohachouch
Man I keep my fingers crossed your workaround does it´s job. I will give it a try.... Thanks!

@hided
Copy link

hided commented Dec 1, 2022

I'm struggling to understand how an issue as prominent as this one, a hard crash on android when simply displaying an image and tabbing away and back, has been seemingly ignored for so long and even moved to the backlog (on another referenced similar issue).

Thanks a lot @mohachouch for your time investigating and seemingly finding a workaround. Will definitely try this one later today.

@FM1973
Copy link

FM1973 commented Dec 1, 2022

@mohachouch
So far no crash the whole day! Thanks a lot!
I can´t understand why the team was not able to provide a solution as quick as you.
I know there is a lot to fix in maui, but this one made android apps unusable.
Thanks again!

@mohachouch
Copy link
Contributor

mohachouch commented Dec 2, 2022

Your welcome @FM1973

I remind you that the workaround is not a correction, it's just for waiting a more permanent fix.

I noticed an strange thing, in my case I don't have to clear but just to declare the method is enough to fix the bug.

@FM1973 can you check that it works on your side ?

Not applying this workarround does not work for everyone

#if __ANDROID__
    public static void PrependToMappingImageSource(IImageHandler handler, Microsoft.Maui.IImage image)
    {
    }
#endif

@jsuarezruiz @mattleibow

According to the source code, assignment of item is done asynchronously, may be related to that :

https://github.com/dotnet/maui/blob/main/src/Core/src/Handlers/Image/ImageHandler.Android.cs#L51

@FM1973
Copy link

FM1973 commented Dec 2, 2022

@mohachouch
Yes, I know it´s only a workaround and it is marked as such in our source code.
I will check if only declaring the method is enough, I can´t before next week, but will get back to you when done.

@1357310795
Copy link

@mohachouch
Not really. Still get the error without handler.PlatformView?.Clear(); With handler.PlatformView?.Clear(); all is OK.

image

image

@FM1973
Copy link

FM1973 commented Dec 2, 2022

@mohachouch @1357310795
Same here. Removing Clear is bringing back instability.

@mohachouch
Copy link
Contributor

mohachouch commented Dec 2, 2022

Thank you for the tests, I do not understand why on my test it works.

It's safer to clear anyway while waiting for Microsoft's fix.

@samhouts samhouts added the p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint label Dec 17, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jan 27, 2023
@samhouts samhouts added the fixed-in-7.0.59 Look for this fix in 7.0.59! label Feb 16, 2023
@samhouts samhouts modified the milestones: Backlog, .NET 7 + Servicing Feb 16, 2023
@samhouts samhouts added the fixed-in-8.0.0-preview.1.7762 Look for this fix in 8.0.0-preview.1.7762! label Feb 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView fixed-in-7.0.59 Look for this fix in 7.0.59! fixed-in-7.0.100 fixed-in-7.0.101 fixed-in-8.0.0-preview.1.7762 Look for this fix in 8.0.0-preview.1.7762! high It doesn't work at all, crashes or has a big impact. p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 t/bug Something isn't working
Projects
None yet