我正在编写Windows Phone 8.1(WINRT)应用程序。
它显示从互联网获取的图像。
我想将此图像保存到本地存储,然后显示它。
我的意思是,每次打开应用程序时,它都会检查图像是否在本地存储中,进行显示并从Internet并行加载该图像的新副本,然后将ui刷新为新图像。
意味着,在从Internet加载新的图像副本之前,将从本地存储中获取的该图像的缓存副本用作占位符。
但是问题是我将获得空白UI,直到从Internet加载图像为止,而不是将本地图像用作占位符。
C#
public sealed partial class ProfileView : Page
{
const string PROFILE_PIC_FILE_NAME = "UmangProfilePic.jpg";
public ProfileView()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
//Testing:
//string url = "http://www.nokia.com/sites/default/files/styles/medium/public/media/nokia_white_logo.png"; //small image
string url = "http://anderson.chem.ox.ac.uk/images/group2015.jpg"; //large image
await UmangImageCacheAsync(url);
}
/// <summary>
/// Check if image exists in local storage, load that image to UI control
/// Then, get latest image from internet and storage that image in local storage
/// Then, load that new image from local storage again to UI control
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private async Task UmangImageCacheAsync(string url)
{
loadingProfilePic.IsActive = true;
//var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
//var ignored = dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
//{
//});
var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
var ignored = dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (await FileExists(PROFILE_PIC_FILE_NAME))
{
profilePicImage.Source = await GetLocalImageAsync();
}
});
var result = await GetRemoteImageAsync(url);
if (result is BitmapImage)
{
profilePicImage.Source = result as BitmapImage;
loadingProfilePic.IsActive = false;
}
else
{
loadingProfilePic.IsActive = false;
}
}
private async Task<BitmapImage> GetLocalImageAsync()
// private async Task<bool> GetLocalImageAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.GetFileAsync(PROFILE_PIC_FILE_NAME);
var image = await FileIO.ReadBufferAsync(file);
Uri uri = new Uri(file.Path);
return new BitmapImage(new Uri(file.Path));
//return true;
}
private static async Task<object> GetRemoteImageAsync(string url)
//private static async Task GetRemoteImageAsync(string url)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.CreateFileAsync(PROFILE_PIC_FILE_NAME, CreationCollisionOption.ReplaceExisting);
HttpClient client = new HttpClient();
try
{
byte[] responseBytes = await client.GetByteArrayAsync(url);
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
using (var outputStream = stream.GetOutputStreamAt(0))
{
DataWriter writer = new DataWriter(outputStream);
writer.WriteBytes(responseBytes);
await writer.StoreAsync();
await outputStream.FlushAsync();
}
var image = await FileIO.ReadBufferAsync(file);
Uri uri = new Uri(file.Path);
return new BitmapImage(new Uri(file.Path));
}
catch (Exception _ex)
{
return false;
}
}
public static async Task<bool> FileExists(string fileName)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
try
{
StorageFile file = await localFolder.GetFileAsync(fileName);
}
catch (Exception _fileEx)
{
return false;
}
return true;
}
}
XAML:
<Grid>
<Grid>
<Image
x:Name="profilePicImage"
Width="400"
Height="400" />
<ProgressRing x:Name="loadingProfilePic"
IsActive="False"
IsEnabled="True" >
</ProgressRing>
</Grid>
</Grid>
要重现此问题:请使用第一个“ url”(小图片)执行应用,
然后使用第二个网址再次调试,注释第一个网址,直到
从互联网上下载新图片,第一个图片应充当
占位符,但您将看到的只是进度环
最佳答案
对GetLocalImageAsync()的调用在对GetRemoteImageAsync()的调用之后执行,因为将其发布到调度程序队列中。我认为您希望通过另一种方法来完成您的方案。
谢谢,
Stefan Wick-Windows开发人员平台
关于c# - Windows Phone 8.1中的图像缓存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42281256/