The image read by the ImageSource.FromFile method is not reflected in Image.ImageSource.
See original GitHub issueDiscussed in https://github.com/dotnet/maui/discussions/13857
<div type='discussions-op-text'>Originally posted by cat0363 March 13, 2023 The procedure is as follows.
- Convert embedded resource images to binary data.
- Output the binary data of 1. as a file to the cache directory. (Delete the file if it already exists in the cache directory.)
- Read the cache file in 2. by the ImageSource.FromFile method and set it to Image.ImageSource.
I have prepared two images of a car and a bicycle. I placed a button of a car and a bicycle in the page. Display the image corresponding to the pressed button in the page according to steps 1 to 3.
The page layout is as follows.
<Grid RowDefinitions="44,100,*">
<StackLayout Grid.Row="0" Orientation="Horizontal" Spacing="5">
<Button x:Name="btnCar" Text="Car" TextColor="White" BackgroundColor="Blue" WidthRequest="120" Clicked="btnCar_Clicked" />
<Button x:Name="btnBicycle" Text="Bicycle" TextColor="White" BackgroundColor="Blue" WidthRequest="120" Clicked="btnBicycle_Clicked" />
</StackLayout>
<Image Grid.Row="1" x:Name="imgTest" />
</Grid>
The source code for step 1 is as follows.
public static byte[] ResourceImageToByte(Assembly assembly, string resouceId)
{
byte[] data;
using (Stream s = assembly.GetManifestResourceStream(resouceId))
{
long length = s.Length;
data = new byte[length];
s.Read(data, 0, (int)length);
}
return data;
}
The source code for steps 2 and 3 is as follows.
public static ImageSource ByteCacheToImageSource(byte[] data, string cacheName = "cache")
{
ImageSource imageSource;
string cachePath = System.IO.Path.Combine(FileSystem.CacheDirectory, cacheName);
if (File.Exists(cachePath))
{
File.Delete(cachePath);
}
File.WriteAllBytes(cachePath, data);
imageSource = ImageSource.FromFile(cachePath);
return imageSource;
}
The processing when pressing the button of the car is as follows.
private void btnCar_Clicked(object sender, EventArgs e)
{
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] imgData = ResourceImageToByte(assembly, "ImageCacheTest.Resources.Images.img1.png");
imgTest.Source = ByteCacheToImageSource(imgData);
}
The processing when pressing the button of the bicycle is as follows.
private void btnBicycle_Clicked(object sender, EventArgs e)
{
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] imgData = ResourceImageToByte(assembly, "ImageCacheTest.Resources.Images.img2.png");
imgTest.Source = ByteCacheToImageSource(imgData);
}
After pressing the car button, pressing the bicycle button displays the image of the car. When I press the bicycle button, I want the image of the bicycle to be displayed, but it is not.
If you delete the cache of the app and press the bicycle button, the image of the bicycle will be displayed, but after that, if you press the car button, the image of the bicycle will be displayed.
If I give the ByteCacheToImageSource method a different cacheName for each button press, it works as intended, but I don’t want that.
Issue #8676 mentions the ImageSource.FromStream method, is this issue also related? If Glide is creating a cache by default by file name or file path, I suspect that’s the cause. Since there is no build environment for iOS, operation cannot be verified. Operation verification was performed on Android.
Any good ideas? Thank you.</div>
Issue Analytics
- State:
- Created 6 months ago
- Comments:8 (5 by maintainers)
It is the same issue, yes. Due to caching it always loads the first image, even if you delete/replace the original image. A workaround is to write images to disk giving each one a unique name. This PR should fix it #13111
Hi, @rodrigoavots Presumably it was resolved with the backport of PR #13111. Thank you for the workaround information.