When developing apps using the Xamarin platform there’s an easy way to load images in code-behind. But it comes with a gotcha. Read on.
The basics
The ImageSource class has a few helper methods to easily load images in various ways. I commonly use it when I want to bind my xaml to a dynamically loaded image. It could be binding to a profile photo loaded from the server. BUT: when doing this I found it was quite easy to generate exceptions. Example code:
ProfilePhoto = ImageSource.FromStream(() => profilePhotoMemoryStream);
The code above looks simple enough. The FromStream
method takes a factory method that should return a Stream
representing the photo.
So, what’s the problem?
Well, the documentation actually specifies what to do, and we’ve all read the docs, right? 😉
The FromStream
method expects a factory
function. Keyword here being factory
. This means that every time the FromStream
method is called (by the xaml renderer), it should return a new stream. So, change the above code to:
The solution
byte[] profilePhotoByteArray = ...
ProfilePhoto = ImageSource.FromStream(() => new MemoryStream(profilePhotoByteArray));
What we do here is keep a byte array
around, and generate a new stream upon every invocation. Don’t worrry, the xaml renderer will Dispose()
the stream, so we’re all good 🙂
A note on image caching
It’s very common to want to cache images locally. It speeds up the UI and is generally a Smart Thing™ to do. Give the information above, you want to cache and return byte
arrays from your image cache implementation, not MemoryStream
s, which would otherwise be the obvious choice.
The good thing is that creating a new MemoryStream
from an existing byte
array, which is already in memory, is fast and cheap.