我正在编写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/

10-13 07:47
查看更多