私はWindows Phone 8.1(WINRT)アプリケーションを作成しています。 インターネットからの画像を表示します。Windows Phone 8.1のイメージキャッシュ
このイメージをローカルストレージに保存して表示します。 私が言っていることは、アプリが開くたびに、画像がローカルストレージにあるかどうかを確認し、それを表示し、インターネットからこの画像の新しいコピーを並列にロードし、uiを新しい画像に更新することです。
画像の新しいコピーがインターネットから読み込まれるまでは、ローカルストレージから取得したこの画像のキャッシュコピーは、のようになります。
しかし、プレースホルダとして機能するローカルイメージではなく、インターネットからイメージが読み込まれるまで、空白の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"(小画像)を使用してアプリケーションを実行し、 は再びdebugg第使用URL インターネットから新しい画像をダウンロードするまでの最初のURLをコメントするURL、最初の画像は プレースホルダとして機能していますが、ディスパッチャキューに掲載されているので、何を観察することは、進捗リングGetLocalImageAsyncにのみ
あなたはいつもそれが新しいコンテンツのインターネットのロード中に表示すべきか、プレースホルダオプションを持っているhttp://coding4fun.codeplex.comからSuperImageコントロールを使用して試みることができます – Depechie