【发布时间】:2017-02-16 17:50:32
【问题描述】:
我正在编写一个 Windows Phone 8.1 (WINRT) 应用程序。 它显示从互联网获取的图像。
我想将此图像保存到本地存储,然后再显示。 我的意思是,每次应用程序打开时,它都会检查图像是否在本地存储中,显示它并从互联网并行加载该图像的新副本,并将 ui 刷新到新图像。
意味着,在从 Internet 加载图像的新副本之前,从本地存储中获取的该图像的缓存副本将充当 占位符。
但问题是我得到空白 UI,直到图像从互联网加载,而不是本地图像充当占位符。
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”(小图像)执行应用程序, 然后再次使用第二个 url 调试第一个 url 直到 从互联网下载新图像,第一张图像应作为 占位符,但您将观察到的只是进度环
【问题讨论】:
-
您可以随时尝试使用来自coding4fun.codeplex.com 的 SuperImage 控件,它有一个占位符选项,在 Internet 加载新内容时应显示的内容
标签: c# windows-phone-8 windows-phone-8.1 windows-phone