I have a function in my Xamarin.Forms app. I'm currently pushing the app to the latest version of all dependancies in preparation for MAUI migration.
The functions purpose is to gather all of the conversations for the messenger section of the app (simplified into a function to reduce Firebase calls as the list is used in two places of the app). What I am finding is that by the time the list is loaded into the ListView on the page, the ImageSource elements within the List<> have been disposed by the GC (I'm assuming because the app has left the scope of the function so it's contents including it's return value is scrapped but i'm not sure).
How can I get this working? It worked in the previous version of Xamarin.Forms and .NET but me thinks I need to improve it's efficiency as the effectiveness of the GC must have been improved in the newer versions.
The function in question:
public static async void GetConversations()
{
Console.WriteLine("ran!");
IQuerySnapshot conversations = await App.Firestore.Collection("conversations").WhereEqualsTo("Members." + App.Authentication.CurrentUser.Uid, true).GetAsync();
foreach (IDocumentSnapshot doc in conversations.Documents)
{
Conversation convo = doc.ToObject<Conversation>();
convo.GetLatests(doc.Id);
string uid = convo.Members.Keys.Where(x => !x.Contains(App.Authentication.CurrentUser.Uid)).First();
ImageSource profile = await ImageHandle.GetProfileImage(uid);
ConversationsList.Add(new KeyValuePair<Conversation, ImageSource>(convo, profile));
}
ConversationsReady?.Invoke(ConversationsList, new EventArgs());
}
And the GetProfileImage() function of ImageHandle:
public static async Task<ImageSource> GetProfileImage(string userID)
{
try
{
System.IO.Stream imageStream = await App.FirebaseStorage.GetInstanceFromUrl("gs://av_profile_images").RootReference.Child(userID + "_1080x1080.jpeg").GetStreamAsync();
return ImageSource.FromStream(() => imageStream);
}
catch (FirebaseStorageException e)
{
Console.WriteLine("Failed to get profile image!");
App.Crashlytics.LogError(e, "Failed to get profile image");
return ImageSource.FromFile("ProfilePlaceholder");
}
}
And finally the exception (two part):
[OpenGLRenderer] --- Failed to create image decoder with message 'unimplemented'
Resolved pending breakpoint at 'ImageHandle.cs:53,1' to void AV.Resources.Extensions.ImageHandle.<GetPostImage>d__2.MoveNext () [0x0011f].
[istsandvenue.AV] Attempt to remove index outside index area (0 vs 1-1)
[istsandvenue.AV] JNI WARNING: DeleteLocalRef(0x19) failed to find entry
[istsandvenue.AV] at mono.android.runtime.InputStreamAdapter.n_read(Native method)
[istsandvenue.AV] at mono.android.runtime.InputStreamAdapter.read(InputStreamAdapter.java:57)
[istsandvenue.AV] at android.graphics.BitmapFactory.nativeDecodeStream(Native method)
[istsandvenue.AV] at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:791)
[istsandvenue.AV] at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:766)
[istsandvenue.AV] at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:807)
Image loading: Image load failed: System.ObjectDisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.EnsureNotClosed () [0x00008] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/MemoryStream.cs:121
at System.IO.MemoryStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 count) [0x0004e] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/MemoryStream.cs:369
at Android.Runtime.InputStreamAdapter.Read (System.Byte[] bytes, System.Int32 offset, System.Int32 length) [0x00000] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/InputStreamAdapter.cs:38
at Java.IO.InputStream.n_Read_arrayBII (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_b, System.Int32 off, System.Int32 len) [0x0001f] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-33/mcw/Java.IO.InputStream.cs:274
at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I (_JniMarshal_PPLII_I callback, System.IntPtr jnienv, System.IntPtr klazz, System.IntPtr p0, System.Int32 p1, System.Int32 p2) [0x00005] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:264
at (wrapper native-to-managed) Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I(intptr,intptr,intptr,int,int)
at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_call_static_object_method_a(intptr,intptr&,intptr,intptr,intptr)
at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0003f] in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/JniEnvironment.g.cs:12886
at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) [0x00008] in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniStaticMethods.cs:151
at Android.Graphics.BitmapFactory.DecodeStream (System.IO.Stream is) [0x0001f] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-33/mcw/Android.Graphics.BitmapFactory.cs:835
at Android.Graphics.BitmapFactory+<>c__DisplayClass31_0.<DecodeStreamAsync>b__0 () [0x00000] in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-33/mcw/Android.Graphics.BitmapFactory.cs:845
at System.Threading.Tasks.Task`1[TResult].InnerInvoke () [0x0000f] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs:534
at System.Threading.Tasks.Task.Execute () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs:2319
--- End of stack trace from previous location where exception was thrown ---
at Xamarin.Forms.Platform.Android.StreamImagesourceHandler.LoadImageAsync (Xamarin.Forms.ImageSource imagesource, Android.Content.Context context, System.Threading.CancellationToken cancelationToken) [0x000da] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\StreamImagesourceHandler.cs:19
at Xamarin.Forms.Platform.Android.ResourceManager.GetFormsBitmapAsync (Android.Content.Context context, Xamarin.Forms.ImageSource imageSource, System.Threading.CancellationToken cancellationToken) [0x0006d] in D:\a\1\s\Xamarin.Forms.Platform.Android\ResourceManager.cs:152
ImageLoaderSourceHandler: Image data was invalid: Xamarin.Forms.StreamImageSource
After this error the app carries on for a few more lines and then crashes when the debugger catches up providing only:
[libc] Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xb83cd000000008 in tid 12022 (istsandvenue.AV), pid 12022 (istsandvenue.AV)
I'm a complete noob when it comes to diagnosing issues when the compiler doesn't give me direction so I'm assuming the fatal interrupt in connection between the debugger and the app instance is due to the most recent error that i've provided above but again - this is only an assumption i'm not certain.
Many Thanks in advance,
Matthew